Merge
authorduke
Wed, 05 Jul 2017 21:00:20 +0200
changeset 33682 88d20346e6f4
parent 33681 7ff3446300cd (current diff)
parent 33678 24293fc3556a (diff)
child 33697 cbe3f1d610ff
Merge
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlotValue.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/UnsignedMath.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualStackSlot.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/Compiler.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/CompilerFactory.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/StartupEventListener.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SuppressFBWarnings.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/JVMCIJarsOptionDescriptorsProvider.java
hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.Compiler
hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.CompilerFactory
hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.config
hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.java
--- a/.hgtags-top-repo	Thu Nov 12 18:27:55 2015 -0800
+++ b/.hgtags-top-repo	Wed Jul 05 21:00:20 2017 +0200
@@ -334,3 +334,4 @@
 895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89
 cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90
 122142a185381ce5cea959bf13b923d8cc333628 jdk9-b91
+106c06398f7ab330eef9e335fbd3a5a8ead23b77 jdk9-b92
--- a/common/autoconf/configure.ac	Thu Nov 12 18:27:55 2015 -0800
+++ b/common/autoconf/configure.ac	Wed Jul 05 21:00:20 2017 +0200
@@ -155,6 +155,9 @@
 #
 ###############################################################################
 
+# See if we are doing a complete static build or not
+JDKOPT_SETUP_STATIC_BUILD
+
 # First determine the toolchain type (compiler family)
 TOOLCHAIN_DETERMINE_TOOLCHAIN_TYPE
 
--- a/common/autoconf/flags.m4	Thu Nov 12 18:27:55 2015 -0800
+++ b/common/autoconf/flags.m4	Wed Jul 05 21:00:20 2017 +0200
@@ -221,7 +221,11 @@
 
     if test "x$OPENJDK_TARGET_OS" = xmacosx; then
       # Linking is different on MacOSX
-      SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
+      if test "x$STATIC_BUILD" = xtrue; then
+        SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup'
+      else
+        SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
+      fi
       SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.'
       SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
       SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/[$]1'
@@ -696,7 +700,9 @@
   COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \
       -I${JDK_TOPDIR}/src/java.base/share/native/include \
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \
-      -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include"
+      -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \
+      -I${JDK_TOPDIR}/src/java.base/share/native/libjava \ 
+      -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava"
 
   # The shared libraries are compiled using the picflag.
   CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
--- a/common/autoconf/generated-configure.sh	Thu Nov 12 18:27:55 2015 -0800
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 21:00:20 2017 +0200
@@ -803,6 +803,7 @@
 SHARED_LIBRARY_SUFFIX
 LIBRARY_PREFIX
 TOOLCHAIN_TYPE
+STATIC_BUILD
 BUILD_HOTSPOT
 HOTSPOT_DIST
 BUILD_OUTPUT
@@ -1074,6 +1075,7 @@
 with_override_nashorn
 with_override_jdk
 with_import_hotspot
+enable_static_build
 with_toolchain_type
 with_extra_cflags
 with_extra_cxxflags
@@ -1852,6 +1854,7 @@
                           run the Queens test after Hotspot build [disabled]
   --enable-unlimited-crypto
                           Enable unlimited crypto policy [disabled]
+  --enable-static-build   enable static library build [disabled]
   --disable-warnings-as-errors
                           do not consider native warnings to be an error
                           [enabled]
@@ -3989,6 +3992,15 @@
 #
 
 
+################################################################################
+#
+# Static build support.  When enabled will generate static
+# libraries instead of shared libraries for all JDK libs.
+#
+
+
+
+
 #
 # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -29018,6 +29030,40 @@
 #
 ###############################################################################
 
+# See if we are doing a complete static build or not
+
+  # Check whether --enable-static-build was given.
+if test "${enable_static_build+set}" = set; then :
+  enableval=$enable_static_build;
+fi
+
+  STATIC_BUILD=false
+  if test "x$enable_static_build" = "xyes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if static build is enabled" >&5
+$as_echo_n "checking if static build is enabled... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    if test "x$OPENJDK_TARGET_OS" != "xmacosx"; then
+      as_fn_error $? "--enable-static-build is only supported for macosx builds" "$LINENO" 5
+    fi
+    STATIC_BUILD_CFLAGS="-DSTATIC_BUILD=1"
+    LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $STATIC_BUILD_CFLAGS"
+    LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $STATIC_BUILD_CFLAGS"
+    CFLAGS_JDKLIB_EXTRA="$CFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS"
+    CXXFLAGS_JDKLIB_EXTRA="$CXXFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS"
+    STATIC_BUILD=true
+  elif test "x$enable_static_build" = "xno"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if static build is enabled" >&5
+$as_echo_n "checking if static build is enabled... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  elif test "x$enable_static_build" != "x"; then
+    as_fn_error $? "--enable-static-build can only be assigned \"yes\" or \"no\"" "$LINENO" 5
+  fi
+
+
+
+
 # First determine the toolchain type (compiler family)
 
 
@@ -29126,8 +29172,19 @@
     OBJ_SUFFIX='.o'
     EXE_SUFFIX=''
     if test "x$OPENJDK_TARGET_OS" = xmacosx; then
-      SHARED_LIBRARY='lib$1.dylib'
-      SHARED_LIBRARY_SUFFIX='.dylib'
+      # For full static builds, we're overloading the SHARED_LIBRARY
+      # variables in order to limit the amount of changes required.
+      # It would be better to remove SHARED and just use LIBRARY and
+      # LIBRARY_SUFFIX for libraries that can be built either
+      # shared or static and use STATIC_* for libraries that are
+      # always built statically.
+      if test "x$STATIC_BUILD" = xtrue; then
+        SHARED_LIBRARY='lib$1.a'
+        SHARED_LIBRARY_SUFFIX='.a'
+      else
+        SHARED_LIBRARY='lib$1.dylib'
+        SHARED_LIBRARY_SUFFIX='.dylib'
+      fi
     fi
   fi
 
@@ -44314,7 +44371,11 @@
 
     if test "x$OPENJDK_TARGET_OS" = xmacosx; then
       # Linking is different on MacOSX
-      SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
+      if test "x$STATIC_BUILD" = xtrue; then
+        SHARED_LIBRARY_FLAGS ='-undefined dynamic_lookup'
+      else
+        SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
+      fi
       SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.'
       SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
       SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/$1'
@@ -44818,7 +44879,9 @@
   COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \
       -I${JDK_TOPDIR}/src/java.base/share/native/include \
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \
-      -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include"
+      -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \
+      -I${JDK_TOPDIR}/src/java.base/share/native/libjava \
+      -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava"
 
   # The shared libraries are compiled using the picflag.
   CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
--- a/common/autoconf/jdk-options.m4	Thu Nov 12 18:27:55 2015 -0800
+++ b/common/autoconf/jdk-options.m4	Wed Jul 05 21:00:20 2017 +0200
@@ -665,3 +665,37 @@
 
   AC_SUBST(GCOV_ENABLED)
 ])
+
+################################################################################
+#
+# Static build support.  When enabled will generate static 
+# libraries instead of shared libraries for all JDK libs.
+#
+AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_BUILD],
+[
+  AC_ARG_ENABLE([static-build], [AS_HELP_STRING([--enable-static-build],
+    [enable static library build @<:@disabled@:>@])])
+  STATIC_BUILD=false
+  if test "x$enable_static_build" = "xyes"; then
+    AC_MSG_CHECKING([if static build is enabled])
+    AC_MSG_RESULT([yes])
+    if test "x$OPENJDK_TARGET_OS" != "xmacosx"; then
+      AC_MSG_ERROR([--enable-static-build is only supported for macosx builds])
+    fi
+    STATIC_BUILD_CFLAGS="-DSTATIC_BUILD=1"
+    LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $STATIC_BUILD_CFLAGS"
+    LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $STATIC_BUILD_CFLAGS"
+    CFLAGS_JDKLIB_EXTRA="$CFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS"
+    CXXFLAGS_JDKLIB_EXTRA="$CXXFLAGS_JDKLIB_EXTRA $STATIC_BUILD_CFLAGS"
+    STATIC_BUILD=true
+  elif test "x$enable_static_build" = "xno"; then
+    AC_MSG_CHECKING([if static build is enabled])
+    AC_MSG_RESULT([no])
+  elif test "x$enable_static_build" != "x"; then
+    AC_MSG_ERROR([--enable-static-build can only be assigned "yes" or "no"])
+  fi
+
+  AC_SUBST(STATIC_BUILD)
+])
+
+
--- a/common/autoconf/spec.gmk.in	Thu Nov 12 18:27:55 2015 -0800
+++ b/common/autoconf/spec.gmk.in	Wed Jul 05 21:00:20 2017 +0200
@@ -417,6 +417,7 @@
 STATIC_LIBRARY_SUFFIX:=@STATIC_LIBRARY_SUFFIX@
 EXE_SUFFIX:=@EXE_SUFFIX@
 OBJ_SUFFIX:=@OBJ_SUFFIX@
+STATIC_BUILD:=@STATIC_BUILD@
 
 STRIPFLAGS:=@STRIPFLAGS@
 
--- a/common/autoconf/toolchain.m4	Thu Nov 12 18:27:55 2015 -0800
+++ b/common/autoconf/toolchain.m4	Wed Jul 05 21:00:20 2017 +0200
@@ -72,8 +72,19 @@
     OBJ_SUFFIX='.o'
     EXE_SUFFIX=''
     if test "x$OPENJDK_TARGET_OS" = xmacosx; then
-      SHARED_LIBRARY='lib[$]1.dylib'
-      SHARED_LIBRARY_SUFFIX='.dylib'
+      # For full static builds, we're overloading the SHARED_LIBRARY
+      # variables in order to limit the amount of changes required.
+      # It would be better to remove SHARED and just use LIBRARY and
+      # LIBRARY_SUFFIX for libraries that can be built either 
+      # shared or static and use STATIC_* for libraries that are 
+      # always built statically.
+      if test "x$STATIC_BUILD" = xtrue; then
+        SHARED_LIBRARY='lib[$]1.a'
+        SHARED_LIBRARY_SUFFIX='.a'
+      else
+        SHARED_LIBRARY='lib[$]1.dylib'
+        SHARED_LIBRARY_SUFFIX='.dylib'
+      fi
     fi
   fi
 
--- a/hotspot/.hgignore	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/.hgignore	Wed Jul 05 21:00:20 2017 +0200
@@ -11,3 +11,12 @@
 ^.hgtip
 .DS_Store
 \.class$
+^\.?mx.jvmci/
+^src/jdk.vm.ci/share/classes/\w[\w\.]*/.*\.xml
+^src/jdk.vm.ci/share/classes/\w[\w\.]*/.*\.iml
+^src/jdk.vm.ci/share/classes/\w[\w\.]*/nbproject
+^src/jdk.vm.ci/share/classes/\w[\w\.]*/\..*
+^test/compiler/jvmci/\w[\w\.]*/.*\.xml
+^test/compiler/jvmci/\w[\w\.]*/.*\.iml
+^test/compiler/jvmci/\w[\w\.]*/nbproject
+^test/compiler/jvmci/\w[\w\.]*/\..*
--- a/hotspot/.hgtags	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/.hgtags	Wed Jul 05 21:00:20 2017 +0200
@@ -494,3 +494,4 @@
 20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89
 7fe46dc64bb3a8df554b24cde0153ffb24f39c5e jdk9-b90
 3fd5c2ca4c20c183628b6dbeb8df821a961419e3 jdk9-b91
+53cb98d68a1aeb08d29c89d6da748de60c448e37 jdk9-b92
--- a/hotspot/agent/src/os/linux/symtab.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/agent/src/os/linux/symtab.c	Wed Jul 05 21:00:20 2017 +0200
@@ -545,6 +545,7 @@
      return (uintptr_t)NULL;
 
   item.key = (char*) strdup(sym_name);
+  item.data = NULL;
   hsearch_r(item, FIND, &ret, symtab->hash_table);
   if (ret) {
     struct elf_symbol * sym = (struct elf_symbol *)(ret->data);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java	Wed Jul 05 21:00:20 2017 +0200
@@ -40,8 +40,7 @@
   // FIXME: access should be synchronized and cleared when VM is
   // resumed
   // String fields
-  private static IntField offsetField;
-  private static IntField countField;
+  private static ByteField coderField;
   private static OopField valueField;
   // ThreadGroup fields
   private static OopField threadGroupParentField;
@@ -96,20 +95,30 @@
     if (charArray == null) {
       return null;
     }
-    return charArrayToString(charArray, 0, (int) charArray.getLength());
+    int length = (int)charArray.getLength();
+    StringBuffer buf = new StringBuffer(length);
+    for (int i = 0; i < length; i++) {
+      buf.append(charArray.getCharAt(i));
+    }
+    return buf.toString();
   }
 
-  public static String charArrayToString(TypeArray charArray, int offset, int length) {
-    if (charArray == null) {
+  public static String byteArrayToString(TypeArray byteArray, byte coder) {
+    if (byteArray == null) {
       return null;
     }
-    final int limit = offset + length;
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(offset >= 0 && limit <= charArray.getLength(), "out of bounds");
-    }
+    int length = (int)byteArray.getLength() >> coder;
     StringBuffer buf = new StringBuffer(length);
-    for (int i = offset; i < limit; i++) {
-      buf.append(charArray.getCharAt(i));
+    if (coder == 0) {
+      // Latin1 encoded
+      for (int i = 0; i < length; i++) {
+        buf.append((char)(byteArray.getByteAt(i) & 0xff));
+      }
+    } else {
+      // UTF16 encoded
+      for (int i = 0; i < length; i++) {
+        buf.append(byteArray.getCharAt(i));
+      }
     }
     return buf.toString();
   }
@@ -141,21 +150,14 @@
   }
 
   public static String stringOopToString(Oop stringOop) {
-    if (offsetField == null) {
-      InstanceKlass k = (InstanceKlass) stringOop.getKlass();
-      offsetField = (IntField) k.findField("offset", "I");   // optional
-      countField  = (IntField) k.findField("count",  "I");   // optional
-      valueField  = (OopField) k.findField("value",  "[C");
-      if (Assert.ASSERTS_ENABLED) {
-         Assert.that(valueField != null, "Field \'value\' of java.lang.String not found");
-      }
+    InstanceKlass k = (InstanceKlass) stringOop.getKlass();
+    coderField  = (ByteField) k.findField("coder", "B");
+    valueField  = (OopField) k.findField("value",  "[B");
+    if (Assert.ASSERTS_ENABLED) {
+       Assert.that(coderField != null, "Field \'coder\' of java.lang.String not found");
+       Assert.that(valueField != null, "Field \'value\' of java.lang.String not found");
     }
-    if (offsetField != null && countField != null) {
-      return charArrayToString((TypeArray) valueField.getValue(stringOop),
-                               offsetField.getValue(stringOop),
-                               countField.getValue(stringOop));
-    }
-    return  charArrayToString((TypeArray) valueField.getValue(stringOop));
+    return byteArrayToString((TypeArray) valueField.getValue(stringOop), coderField.getValue(stringOop));
   }
 
   public static String stringOopToEscapedString(Oop stringOop) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Wed Jul 05 21:00:20 2017 +0200
@@ -268,8 +268,8 @@
             VM vm = VM.getVM();
             SystemDictionary sysDict = vm.getSystemDictionary();
             InstanceKlass strKlass = sysDict.getStringKlass();
-            // String has a field named 'value' of type 'char[]'.
-            stringValueField = (OopField) strKlass.findField("value", "[C");
+            // String has a field named 'value' of type 'byte[]'.
+            stringValueField = (OopField) strKlass.findField("value", "[B");
          }
 
          private long stringSize(Instance instance) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java	Wed Jul 05 21:00:20 2017 +0200
@@ -61,9 +61,8 @@
     long h = 0;
     int s = 0;
     int len = buf.length;
-    // Emulate the unsigned int in java_lang_String::hash_code
     while (len-- > 0) {
-      h = 31*h + (0xFFFFFFFFL & buf[s]);
+      h = 31*h + (0xFFL & buf[s]);
       s++;
     }
     return h & 0xFFFFFFFFL;
--- a/hotspot/make/Makefile	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/Makefile	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -403,6 +403,8 @@
 	$(install-dir)
 $(EXPORT_SERVER_DIR)/%.dSYM:       		$(C2_BUILD_DIR)/%.dSYM
 	$(install-dir)
+$(EXPORT_SERVER_DIR)/%.symbols:                 $(C2_BUILD_DIR)/%.symbols
+	$(install-file)
 endif
 
 # Client (C1)
--- a/hotspot/make/bsd/makefiles/buildtree.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/bsd/makefiles/buildtree.make	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -224,6 +224,11 @@
 	echo "OPENJDK = $(OPENJDK)"; \
 	echo "$(LP64_SETTING/$(DATA_MODE))"; \
 	echo; \
+	echo "STATIC_BUILD = $(STATIC_BUILD)"; \
+	echo "COMPILER_WARNINGS_FATAL = $(COMPILER_WARNINGS_FATAL)"; \
+	echo "EXTRA_LDFLAGS = $(EXTRA_LDFLAGS)"; \
+	echo "LIBRARY_SUFFIX = $(LIBRARY_SUFFIX)"; \
+	echo; \
 	echo "# Used for platform dispatching"; \
 	echo "TARGET_DEFINES  = -DTARGET_OS_FAMILY_\$$(Platform_os_family)"; \
 	echo "TARGET_DEFINES += -DTARGET_ARCH_\$$(Platform_arch)"; \
--- a/hotspot/make/bsd/makefiles/defs.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/bsd/makefiles/defs.make	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -186,13 +186,16 @@
   # executed multiple times. We reduce the noise by at least checking that
   # BUILD_FLAVOR has been set.
   ifneq ($(BUILD_FLAVOR),)
-    ifeq ($(BUILD_FLAVOR), product)
-      FULL_DEBUG_SYMBOLS ?= 1
-      ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
-    else
-      # debug variants always get Full Debug Symbols (if available)
-      ENABLE_FULL_DEBUG_SYMBOLS = 1
-    endif
+    # FULL_DEBUG_SYMBOLS not created for individual static libraries
+    ifeq ($(STATIC_BUILD),false)
+      ifeq ($(BUILD_FLAVOR), product)
+        FULL_DEBUG_SYMBOLS ?= 1
+        ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
+      else
+        # debug variants always get Full Debug Symbols (if available)
+        ENABLE_FULL_DEBUG_SYMBOLS = 1
+      endif
+     endif
     $(eval $(call print_info, "ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)"))
     # since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
 
@@ -256,16 +259,24 @@
 JDK_INCLUDE_SUBDIR=bsd
 
 # Library suffix
-ifeq ($(OS_VENDOR),Darwin)
-  LIBRARY_SUFFIX=dylib
+ifneq ($(STATIC_BUILD),true)
+  ifeq ($(OS_VENDOR),Darwin)
+    LIBRARY_SUFFIX=dylib
+  else
+    LIBRARY_SUFFIX=so
+  endif
 else
-  LIBRARY_SUFFIX=so
+  LIBRARY_SUFFIX=a
 endif
 
+
 EXPORT_LIST += $(EXPORT_DOCS_DIR)/platform/jvmti/jvmti.html
 
+# jsig library not needed for static builds
+ifneq ($(STATIC_BUILD),true)
 # client and server subdirectories have symbolic links to ../libjsig.so
-EXPORT_LIST += $(EXPORT_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX)
+  EXPORT_LIST += $(EXPORT_LIB_ARCH_DIR)/libjsig.$(LIBRARY_SUFFIX)
+endif
 
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   ifeq ($(ZIP_DEBUGINFO_FILES),1)
@@ -286,6 +297,9 @@
 ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+  ifeq ($(STATIC_BUILD),true)
+    EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.symbols
+  endif
 
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
     ifeq ($(ZIP_DEBUGINFO_FILES),1)
@@ -303,6 +317,9 @@
 ifeq ($(JVM_VARIANT_CLIENT),true)
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
+  ifeq ($(STATIC_BUILD),true)
+    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.symbols
+  endif
 
   ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
     ifeq ($(ZIP_DEBUGINFO_FILES),1)
@@ -320,6 +337,9 @@
 ifeq ($(JVM_VARIANT_MINIMAL1),true)
   EXPORT_LIST += $(EXPORT_MINIMAL_DIR)/Xusage.txt
   EXPORT_LIST += $(EXPORT_MINIMAL_DIR)/libjvm.$(LIBRARY_SUFFIX)
+  ifeq ($(STATIC_BUILD),true)
+    EXPORT_LIST += $(EXPORT_MINIMAL_DIR)/libjvm.symbols
+  endif
 endif
 
 # Serviceability Binaries
@@ -388,7 +408,9 @@
     endif
 
     # Binaries to 'universalize' if built
-    UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/libjsig.$(LIBRARY_SUFFIX)
+    ifneq ($(STATIC_BUILD),true)
+      UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/libjsig.$(LIBRARY_SUFFIX)
+    endif
     UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/libsaproc.$(LIBRARY_SUFFIX)
     UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/server/libjvm.$(LIBRARY_SUFFIX)
     UNIVERSAL_LIPO_LIST += $(EXPORT_LIB_DIR)/client/libjvm.$(LIBRARY_SUFFIX)
@@ -396,6 +418,13 @@
     # Files to simply copy in place
     UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/server/Xusage.txt
     UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/client/Xusage.txt
+
+    ifeq ($(STATIC_BUILD),true)
+      UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/server/libjvm.symbols
+      UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/client/libjvm.symbols
+      UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/minimal/libjvm.symbols
+    endif
+
     ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
       ifeq ($(ZIP_DEBUGINFO_FILES),1)
           UNIVERSAL_COPY_LIST += $(EXPORT_LIB_DIR)/server/libjvm.diz
--- a/hotspot/make/bsd/makefiles/dtrace.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/bsd/makefiles/dtrace.make	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -37,15 +37,15 @@
 # Bsd does not build libjvm_db, does not compile on macosx
 # disabled in build: rule in vm.make
 JVM_DB = libjvm_db
-LIBJVM_DB = libjvm_db.dylib
+LIBJVM_DB = libjvm_db.$(LIBRARY_SUFFIX)
 
-LIBJVM_DB_DEBUGINFO   = libjvm_db.dylib.dSYM
+LIBJVM_DB_DEBUGINFO   = libjvm_db.$(LIBRARY_SUFFIX).dSYM
 LIBJVM_DB_DIZ         = libjvm_db.diz
 
 JVM_DTRACE = jvm_dtrace
-LIBJVM_DTRACE = libjvm_dtrace.dylib
+LIBJVM_DTRACE = libjvm_dtrace.$(LIBRARY_SUFFIX)
 
-LIBJVM_DTRACE_DEBUGINFO   = libjvm_dtrace.dylib.dSYM
+LIBJVM_DTRACE_DEBUGINFO   = libjvm_dtrace.$(LIBRARY_SUFFIX).dSYM
 LIBJVM_DTRACE_DIZ         = libjvm_dtrace.diz
 
 JVMOFFS = JvmOffsets
@@ -167,14 +167,14 @@
 
 LFLAGS_GENOFFS += -L.
 
-lib$(GENOFFS).dylib: $(DTRACE_SRCDIR)/$(GENOFFS).cpp $(DTRACE_SRCDIR)/$(GENOFFS).h \
+lib$(GENOFFS).$(LIBRARY_SUFFIX): $(DTRACE_SRCDIR)/$(GENOFFS).cpp $(DTRACE_SRCDIR)/$(GENOFFS).h \
                   $(LIBJVM.o)
 	$(QUIETLY) $(CXX) $(CXXFLAGS) $(GENOFFS_CFLAGS) $(SHARED_FLAG) $(PICFLAG) \
 		 $(LFLAGS_GENOFFS) -o $@ $(DTRACE_SRCDIR)/$(GENOFFS).cpp -ljvm
 
-$(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).dylib
+$(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).$(LIBRARY_SUFFIX)
 	$(QUIETLY) $(LINK.CXX) -o $@ $(DTRACE_SRCDIR)/$(GENOFFS)Main.c \
-		./lib$(GENOFFS).dylib
+		./lib$(GENOFFS).$(LIBRARY_SUFFIX)
 
 # $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
 $(JVMOFFS).h: $(GENOFFS)
--- a/hotspot/make/bsd/makefiles/gcc.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/bsd/makefiles/gcc.make	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -187,7 +187,14 @@
   CFLAGS += $(LIBFFI_CFLAGS)
   CFLAGS += $(LLVM_CFLAGS)
 endif
+
+ifeq ($(STATIC_BUILD),true)
+CXXFLAGS += -DSTATIC_BUILD
+CFLAGS += -DSTATIC_BUILD
+else
 CFLAGS += $(VM_PICFLAG)
+endif
+
 CFLAGS += -fno-rtti
 CFLAGS += -fno-exceptions
 ifeq ($(USE_CLANG),)
--- a/hotspot/make/bsd/makefiles/jsig.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/bsd/makefiles/jsig.make	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,9 @@
 JSIG   = jsig
 
 ifeq ($(OS_VENDOR), Darwin)
-  LIBJSIG   = lib$(JSIG).dylib
+  LIBJSIG   = lib$(JSIG).$(LIBRARY_SUFFIX)
 
-  LIBJSIG_DEBUGINFO   = lib$(JSIG).dylib.dSYM
+  LIBJSIG_DEBUGINFO   = lib$(JSIG).$(LIBRARY_SUFFIX).dSYM
   LIBJSIG_DIZ         = lib$(JSIG).diz
 else
   LIBJSIG   = lib$(JSIG).so
@@ -61,8 +61,14 @@
 
 $(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
 	@echo $(LOG_INFO) Making signal interposition lib...
+ifeq ($(STATIC_BUILD),true)
+	$(QUIETLY) $(CC) -c $(SYMFLAG) $(EXTRA_CFLAGS) $(ARCHFLAG) $(PICFLAG) \
+                          $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $(JSIG).o $<
+	$(QUIETLY) $(AR) $(ARFLAGS) $@ $(JSIG).o
+else
 	$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
-                         $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $<
+                          $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $<
+endif
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   ifeq ($(OS_VENDOR), Darwin)
 	$(DSYMUTIL) $@
--- a/hotspot/make/bsd/makefiles/rules.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/bsd/makefiles/rules.make	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,11 @@
 COMPILE.CC       = $(CC_COMPILE) -c
 GENASM.CC        = $(CC_COMPILE) -S
 LINK.CC          = $(CC) $(LFLAGS) $(AOUT_FLAGS) $(PROF_AOUT_FLAGS)
+ifeq ($(STATIC_BUILD),true)
+LINK_LIB.CC      = $(AR) $(ARFLAGS)
+else
 LINK_LIB.CC      = $(CC) $(LFLAGS) $(SHARED_FLAG)
+endif
 PREPROCESS.CC    = $(CC_COMPILE) -E
 
 COMPILE.CXX      = $(CXX_COMPILE) -c
--- a/hotspot/make/bsd/makefiles/saproc.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/bsd/makefiles/saproc.make	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,9 @@
 SAPROC   = saproc
 
 ifeq ($(OS_VENDOR), Darwin)
-  LIBSAPROC           = lib$(SAPROC).dylib
+  LIBSAPROC           = lib$(SAPROC).$(LIBRARY_SUFFIX)
 
-  LIBSAPROC_DEBUGINFO = lib$(SAPROC).dylib.dSYM
+  LIBSAPROC_DEBUGINFO = lib$(SAPROC).$(LIBRARY_SUFFIX).dSYM
   LIBSAPROC_DIZ       = lib$(SAPROC).diz
 else
   LIBSAPROC           = lib$(SAPROC).so
--- a/hotspot/make/bsd/makefiles/vm.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/bsd/makefiles/vm.make	Wed Jul 05 21:00:20 2017 +0200
@@ -142,10 +142,10 @@
 
 JVM    = jvm
 ifeq ($(OS_VENDOR), Darwin)
-  LIBJVM   = lib$(JVM).dylib
+  LIBJVM   = lib$(JVM).$(LIBRARY_SUFFIX)
   CFLAGS  += -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE
 
-  LIBJVM_DEBUGINFO   = lib$(JVM).dylib.dSYM
+  LIBJVM_DEBUGINFO   = lib$(JVM).$(LIBRARY_SUFFIX).dSYM
   LIBJVM_DIZ         = lib$(JVM).diz
 else
   LIBJVM   = lib$(JVM).so
@@ -261,6 +261,16 @@
                  { print $$0 }				\
              }' > $@ < $(MAPFILE)
 
+ifeq ($(STATIC_BUILD),true)
+EXPORTED_SYMBOLS = libjvm.symbols
+
+libjvm.symbols : mapfile
+	$(CP) mapfile libjvm.symbols
+
+else
+EXPORTED_SYMBOLS =
+endif
+
 mapfile_reorder : mapfile $(REORDERFILE)
 	rm -f $@
 	cat $^ > $@
@@ -288,9 +298,11 @@
   LFLAGS_VM                += $(SONAMEFLAG:SONAME=$(LIBJVM))
 
   ifeq ($(OS_VENDOR), Darwin)
-    LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/.
-    LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/..
-    LFLAGS_VM += -Xlinker -install_name -Xlinker @rpath/$(@F)
+    ifneq ($(STATIC_BUILD),true)
+      LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/.
+      LFLAGS_VM += -Xlinker -rpath -Xlinker @loader_path/..
+      LFLAGS_VM += -Xlinker -install_name -Xlinker @rpath/$(@F)
+    endif
   else
     LFLAGS_VM                += -Wl,-z,defs
   endif
@@ -345,6 +357,10 @@
 endif
 
 $(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT)
+ifeq ($(STATIC_BUILD),true)
+	echo Linking static vm...;
+	$(LINK_LIB.CC) $@ $(LIBJVM.o)
+else
 	$(QUIETLY) {                                                    \
 	    echo $(LOG_INFO) Linking vm...;                                         \
 	    $(LINK_LIB.CXX/PRE_HOOK)                                     \
@@ -354,6 +370,8 @@
 	    rm -f $@.1; ln -s $@ $@.1;                                  \
 	}
 
+endif
+
 ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
   ifeq ($(OS_VENDOR), Darwin)
 	$(DSYMUTIL) $@
@@ -410,10 +428,10 @@
 
 ifeq ($(OS_VENDOR), Darwin)
 # no libjvm_db for macosx
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(EXPORTED_SYMBOLS)
 	echo "Doing vm.make build:"
 else
-build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC)
+build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) $(EXPORTED_SYMBOLS)
 endif
 
 install: install_jvm install_jsig install_saproc
--- a/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -56,10 +56,10 @@
 ################################################################################
 
 PROC_SRC_SUBDIRS := \
-    jdk.vm.ci.compiler \
     jdk.vm.ci.hotspot \
     jdk.vm.ci.hotspot.amd64 \
     jdk.vm.ci.hotspot.sparc \
+    jdk.vm.ci.runtime \
     #
 
 PROC_SRC_DIRS := $(patsubst %, $(SRC_DIR)/%/src, $(PROC_SRC_SUBDIRS))
@@ -94,11 +94,7 @@
 $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors: \
     $(GENSRC_DIR)/_gensrc_proc_done
 	$(MKDIR) -p $(@D)
-	($(CD) $(GENSRC_DIR)/META-INF/jvmci.options && \
-	    $(RM) -f $@; \
-	    for i in $$(ls); do \
-	      echo $${i}_OptionDescriptors >> $@; \
-	    done)
+	$(FIND) $(GENSRC_DIR) -name '*_OptionDescriptors.java' | $(SED) 's:.*/jdk\.vm\.ci/\(.*\)\.java:\1:' | $(TR) '/' '.' > $@
 
 TARGETS += $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors
 
--- a/hotspot/make/linux/makefiles/gcc.make	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/make/linux/makefiles/gcc.make	Wed Jul 05 21:00:20 2017 +0200
@@ -61,6 +61,11 @@
   CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
   CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
   CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
+  # Workaround Ubuntu bug where -dumpversion doesn't print a micro version
+  # https://bugs.launchpad.net/ubuntu/+source/gcc-4.8/+bug/1360404
+  ifeq ($(CC_VER_MICRO),)
+    CC_VER_MICRO := "0"
+  endif
 endif
 
 ifeq ($(USE_CLANG), true)
@@ -224,6 +229,8 @@
     WARNING_FLAGS += -Wtype-limits
     # GCC < 4.8 don't accept this flag for C++.
     WARNING_FLAGS += -Wno-format-zero-length
+    # GCC 4.8 reports less false positives than the older compilers.
+    WARNING_FLAGS += -Wuninitialized
   endif
 endif
 
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad	Wed Jul 05 21:00:20 2017 +0200
@@ -14150,6 +14150,7 @@
 instruct string_compare(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cnt2,
                         iRegI_R0 result, iRegP_R10 tmp1, rFlagsReg cr)
 %{
+  predicate(!CompactStrings);
   match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
   effect(KILL tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
 
@@ -14165,6 +14166,7 @@
 instruct string_indexof(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
        iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
 %{
+  predicate(!CompactStrings);
   match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
   effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
          TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
@@ -14184,6 +14186,7 @@
                  immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
                  iRegI tmp3, iRegI tmp4, rFlagsReg cr)
 %{
+  predicate(!CompactStrings);
   match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
   effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1,
          TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
@@ -14203,6 +14206,7 @@
 instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
                         iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr)
 %{
+  predicate(!CompactStrings);
   match(Set result (StrEquals (Binary str1 str2) cnt));
   effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
 
@@ -14218,6 +14222,7 @@
 instruct array_equals(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
                       iRegP_R10 tmp, rFlagsReg cr)
 %{
+  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
   match(Set result (AryEq ary1 ary2));
   effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, KILL cr);
 
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -483,15 +483,6 @@
   return offset;
 }
 
-
-// This is the fast version of java.lang.String.compare; it has not
-// OSR-entry and therefore, we generate a slow version for OSR's
-void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info)  {
-  __ mov(r2, (address)__FUNCTION__);
-  __ call_Unimplemented();
-}
-
-
 void LIR_Assembler::add_debug_info_for_branch(address adr, CodeEmitInfo* info) {
   _masm->code_section()->relocate(adr, relocInfo::poll_type);
   int pc_offset = code_offset();
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -79,6 +79,9 @@
 
 define_pd_global(uintx, TypeProfileLevel, 111);
 
+// No performance work done here yet.
+define_pd_global(bool, CompactStrings, false);
+
 // avoid biased locking while we are bootstrapping the aarch64 build
 define_pd_global(bool, UseBiasedLocking, false);
 
--- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -38,11 +38,11 @@
   Unimplemented();
 }
 
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) {
   Unimplemented();
 }
 
-void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
   Unimplemented();
 }
 
--- a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -62,7 +62,7 @@
 void MethodHandles::verify_klass(MacroAssembler* _masm,
                                  Register obj, SystemDictionary::WKID klass_id,
                                  const char* error_message) {
-  Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
+  InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
   KlassHandle klass = SystemDictionary::well_known_klass(klass_id);
   Register temp = rscratch2;
   Register temp2 = rscratch1; // used by MacroAssembler::cmpptr
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1276,7 +1276,7 @@
 //    return to caller
 //
 nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
-                                                methodHandle method,
+                                                const methodHandle& method,
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -72,6 +72,9 @@
 
 define_pd_global(uintx, TypeProfileLevel, 111);
 
+// No performance work done here yet.
+define_pd_global(bool, CompactStrings, false);
+
 // Platform dependent flag handling: flags only defined on this platform.
 #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint)  \
                                                                             \
--- a/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -38,11 +38,11 @@
   Unimplemented();
 }
 
-void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) {
   Unimplemented();
 }
 
-void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
   Unimplemented();
 }
 
--- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -73,7 +73,7 @@
                                  Register obj_reg, SystemDictionary::WKID klass_id,
                                  Register temp_reg, Register temp2_reg,
                                  const char* error_message) {
-  Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
+  InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
   KlassHandle klass = SystemDictionary::well_known_klass(klass_id);
   Label L_ok, L_bad;
   BLOCK_COMMENT("verify_klass {");
--- a/hotspot/src/cpu/ppc/vm/ppc.ad	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad	Wed Jul 05 21:00:20 2017 +0200
@@ -2054,11 +2054,11 @@
     return (UsePopCountInstruction && VM_Version::has_popcntw());
 
   case Op_StrComp:
-    return SpecialStringCompareTo;
+    return SpecialStringCompareTo && !CompactStrings;
   case Op_StrEquals:
-    return SpecialStringEquals;
+    return SpecialStringEquals && !CompactStrings;
   case Op_StrIndexOf:
-    return SpecialStringIndexOf;
+    return SpecialStringIndexOf && !CompactStrings;
   }
 
   return true;  // Per default match rules are supported.
@@ -11077,7 +11077,7 @@
                                   immP needleImm, immL offsetImm, immI_1 needlecntImm,
                                   iRegIdst tmp1, iRegIdst tmp2,
                                   flagsRegCR0 cr0, flagsRegCR1 cr1) %{
-  predicate(SpecialStringIndexOf);  // type check implicit by parameter type, See Matcher::match_rule_supported
+  predicate(SpecialStringIndexOf && !CompactStrings);  // type check implicit by parameter type, See Matcher::match_rule_supported
   match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
 
   effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
@@ -11120,7 +11120,7 @@
   effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result,
          TEMP tmp1, TEMP tmp2);
   // Required for EA: check if it is still a type_array.
-  predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
+  predicate(SpecialStringIndexOf && !CompactStrings && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
             n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
   ins_cost(180);
 
@@ -11167,7 +11167,7 @@
   effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
          TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6);
   // Required for EA: check if it is still a type_array.
-  predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
+  predicate(SpecialStringIndexOf && !CompactStrings && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
             n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
   ins_cost(250);
 
@@ -11200,7 +11200,7 @@
   effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
          TEMP_DEF result,
          TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6);
-  predicate(SpecialStringIndexOf);  // See Matcher::match_rule_supported.
+  predicate(SpecialStringIndexOf && !CompactStrings);  // See Matcher::match_rule_supported.
   ins_cost(300);
 
   ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
@@ -11224,7 +11224,7 @@
   match(Set result (StrEquals (Binary str1 str2) cntImm));
   effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2,
          KILL cr0, KILL cr6, KILL ctr);
-  predicate(SpecialStringEquals);  // See Matcher::match_rule_supported.
+  predicate(SpecialStringEquals && !CompactStrings);  // See Matcher::match_rule_supported.
   ins_cost(250);
 
   ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
@@ -11247,7 +11247,7 @@
   match(Set result (StrEquals (Binary str1 str2) cnt));
   effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
          KILL cr0, KILL cr1, KILL cr6, KILL ctr);
-  predicate(SpecialStringEquals);  // See Matcher::match_rule_supported.
+  predicate(SpecialStringEquals && !CompactStrings);  // See Matcher::match_rule_supported.
   ins_cost(300);
 
   ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
@@ -11267,6 +11267,7 @@
 // Use dst register classes if register gets killed, as it is the case for TEMP operands!
 instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
                         iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{
+  predicate(!CompactStrings);
   match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
   effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr);
   ins_cost(300);
--- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1701,7 +1701,7 @@
 //   return to caller
 //
 nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
-                                                methodHandle method,
+                                                const methodHandle& method,
                                                 int compile_id,
                                                 BasicType *in_sig_bt,
                                                 VMRegPair *in_regs,
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -124,6 +124,8 @@
     impdep1_op3  = 0x36,
     aes3_op3     = 0x36,
     sha_op3      = 0x36,
+    bmask_op3    = 0x36,
+    bshuffle_op3   = 0x36,
     alignaddr_op3  = 0x36,
     faligndata_op3 = 0x36,
     flog3_op3    = 0x36,
@@ -194,6 +196,7 @@
     fnegd_opf          = 0x06,
 
     alignaddr_opf      = 0x18,
+    bmask_opf          = 0x19,
 
     fadds_opf          = 0x41,
     faddd_opf          = 0x42,
@@ -204,6 +207,7 @@
 
     fmuls_opf          = 0x49,
     fmuld_opf          = 0x4a,
+    bshuffle_opf       = 0x4c,
     fdivs_opf          = 0x4d,
     fdivd_opf          = 0x4e,
 
@@ -1226,6 +1230,9 @@
 
   void edge8n( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(edge_op3) | rs1(s1) | opf(edge8n_opf) | rs2(s2)); }
 
+  void bmask( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(bmask_op3) | rs1(s1) | opf(bmask_opf) | rs2(s2)); }
+  void bshuffle( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis2_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(bshuffle_op3) | fs1(s1, FloatRegisterImpl::D) | opf(bshuffle_opf) | fs2(s2, FloatRegisterImpl::D)); }
+
   // VIS3 instructions
 
   void movstosw( FloatRegister s, Register d ) { vis3_only();  emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); }
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -232,118 +232,6 @@
 }
 
 
-// Optimized Library calls
-// This is the fast version of java.lang.String.compare; it has not
-// OSR-entry and therefore, we generate a slow version for OSR's
-void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst, CodeEmitInfo* info) {
-  Register str0 = left->as_register();
-  Register str1 = right->as_register();
-
-  Label Ldone;
-
-  Register result = dst->as_register();
-  {
-    // Get a pointer to the first character of string0 in tmp0
-    //   and get string0.length() in str0
-    // Get a pointer to the first character of string1 in tmp1
-    //   and get string1.length() in str1
-    // Also, get string0.length()-string1.length() in
-    //   o7 and get the condition code set
-    // Note: some instructions have been hoisted for better instruction scheduling
-
-    Register tmp0 = L0;
-    Register tmp1 = L1;
-    Register tmp2 = L2;
-
-    int  value_offset = java_lang_String:: value_offset_in_bytes(); // char array
-    if (java_lang_String::has_offset_field()) {
-      int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
-      int  count_offset = java_lang_String:: count_offset_in_bytes();
-      __ load_heap_oop(str0, value_offset, tmp0);
-      __ ld(str0, offset_offset, tmp2);
-      __ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
-      __ ld(str0, count_offset, str0);
-      __ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
-    } else {
-      __ load_heap_oop(str0, value_offset, tmp1);
-      __ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
-      __ ld(tmp1, arrayOopDesc::length_offset_in_bytes(), str0);
-    }
-
-    // str1 may be null
-    add_debug_info_for_null_check_here(info);
-
-    if (java_lang_String::has_offset_field()) {
-      int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
-      int  count_offset = java_lang_String:: count_offset_in_bytes();
-      __ load_heap_oop(str1, value_offset, tmp1);
-      __ add(tmp0, tmp2, tmp0);
-
-      __ ld(str1, offset_offset, tmp2);
-      __ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
-      __ ld(str1, count_offset, str1);
-      __ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
-      __ add(tmp1, tmp2, tmp1);
-    } else {
-      __ load_heap_oop(str1, value_offset, tmp2);
-      __ add(tmp2, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
-      __ ld(tmp2, arrayOopDesc::length_offset_in_bytes(), str1);
-    }
-    __ subcc(str0, str1, O7);
-  }
-
-  {
-    // Compute the minimum of the string lengths, scale it and store it in limit
-    Register count0 = I0;
-    Register count1 = I1;
-    Register limit  = L3;
-
-    Label Lskip;
-    __ sll(count0, exact_log2(sizeof(jchar)), limit);             // string0 is shorter
-    __ br(Assembler::greater, true, Assembler::pt, Lskip);
-    __ delayed()->sll(count1, exact_log2(sizeof(jchar)), limit);  // string1 is shorter
-    __ bind(Lskip);
-
-    // If either string is empty (or both of them) the result is the difference in lengths
-    __ cmp(limit, 0);
-    __ br(Assembler::equal, true, Assembler::pn, Ldone);
-    __ delayed()->mov(O7, result);  // result is difference in lengths
-  }
-
-  {
-    // Neither string is empty
-    Label Lloop;
-
-    Register base0 = L0;
-    Register base1 = L1;
-    Register chr0  = I0;
-    Register chr1  = I1;
-    Register limit = L3;
-
-    // Shift base0 and base1 to the end of the arrays, negate limit
-    __ add(base0, limit, base0);
-    __ add(base1, limit, base1);
-    __ neg(limit);  // limit = -min{string0.length(), string1.length()}
-
-    __ lduh(base0, limit, chr0);
-    __ bind(Lloop);
-    __ lduh(base1, limit, chr1);
-    __ subcc(chr0, chr1, chr0);
-    __ br(Assembler::notZero, false, Assembler::pn, Ldone);
-    assert(chr0 == result, "result must be pre-placed");
-    __ delayed()->inccc(limit, sizeof(jchar));
-    __ br(Assembler::notZero, true, Assembler::pt, Lloop);
-    __ delayed()->lduh(base0, limit, chr0);
-  }
-
-  // If strings are equal up to min length, return the length difference.
-  __ mov(O7, result);
-
-  // Otherwise, return the difference between the first mismatched chars.
-  __ bind(Ldone);
-}
-
-
 // --------------------------------------------------------------------------------------------
 
 void LIR_Assembler::monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register hdr, int monitor_no) {
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -86,6 +86,8 @@
 
 define_pd_global(uintx, TypeProfileLevel, 111);
 
+define_pd_global(bool, CompactStrings, true);
+
 #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
                                                                             \
   product(intx, UseVIS, 99,                                                 \
--- a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -66,6 +66,25 @@
   }
 }
 
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) {
+  address pc = _instructions->start() + pc_offset;
+  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+#ifdef _LP64
+    NativeMovConstReg32* move = nativeMovConstReg32_at(pc);
+    narrowKlass narrowOop = record_narrow_metadata_reference(constant);
+    move->set_data((intptr_t)narrowOop);
+    TRACE_jvmci_3("relocating (narrow metaspace constant) at %p/%p", pc, narrowOop);
+#else
+    fatal("compressed Klass* on 32bit");
+#endif
+  } else {
+    NativeMovConstReg* move = nativeMovConstReg_at(pc);
+    Metadata* reference = record_metadata_reference(constant);
+    move->set_data((intptr_t)reference);
+    TRACE_jvmci_3("relocating (metaspace constant) at %p/%p", pc, reference);
+  }
+}
+
 void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
   address pc = _instructions->start() + pc_offset;
   NativeInstruction* inst = nativeInstruction_at(pc);
@@ -87,10 +106,6 @@
   }
 }
 
-void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
-  fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
-}
-
 void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
   address pc = (address) inst;
   if (inst->is_call()) {
@@ -168,16 +183,25 @@
 
 // convert JVMCI register indices (as used in oop maps) to HotSpot registers
 VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
-  if (jvmci_reg < RegisterImpl::number_of_registers) {
+  // JVMCI Registers are numbered as follows:
+  //   0..31: Thirty-two General Purpose registers (CPU Registers)
+  //   32..63: Thirty-two single precision float registers
+  //   64..95: Thirty-two double precision float registers
+  //   96..111: Sixteen quad precision float registers
+  if (jvmci_reg < 32) {
     return as_Register(jvmci_reg)->as_VMReg();
   } else {
-    jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
-    floatRegisterNumber += MAX2(0, floatRegisterNumber-32); // Beginning with f32, only every second register is going to be addressed
-    if (floatRegisterNumber < FloatRegisterImpl::number_of_registers) {
-      return as_FloatRegister(floatRegisterNumber)->as_VMReg();
+    jint floatRegisterNumber;
+    if(jvmci_reg < 64) { // Single precision
+      floatRegisterNumber = jvmci_reg - 32;
+    } else if(jvmci_reg < 96) {
+      floatRegisterNumber = 2 * (jvmci_reg - 64);
+    } else if(jvmci_reg < 112) {
+      floatRegisterNumber = 4 * (jvmci_reg - 96);
+    } else {
+      fatal("Unknown jvmci register");
     }
-    ShouldNotReachHere();
-    return NULL;
+    return as_FloatRegister(floatRegisterNumber)->as_VMReg();
   }
 }
 
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -44,6 +44,9 @@
 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
+#ifdef COMPILER2
+#include "opto/intrinsicnode.hpp"
+#endif
 
 #ifdef PRODUCT
 #define BLOCK_COMMENT(str) /* nothing */
@@ -4253,27 +4256,385 @@
   }
 }
 
-// Compare char[] arrays aligned to 4 bytes.
-void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
-                                        Register limit, Register result,
-                                        Register chr1, Register chr2, Label& Ldone) {
-  Label Lvector, Lloop;
-  assert(chr1 == result, "should be the same");
-
-  // Note: limit contains number of bytes (2*char_elements) != 0.
-  andcc(limit, 0x2, chr1); // trailing character ?
+#ifdef COMPILER2
+
+// Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure.
+void MacroAssembler::string_compress_16(Register src, Register dst, Register cnt, Register result,
+                                        Register tmp1, Register tmp2, Register tmp3, Register tmp4,
+                                        FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone) {
+  Label Lloop, Lslow;
+  assert(UseVIS >= 3, "VIS3 is required");
+  assert_different_registers(src, dst, cnt, tmp1, tmp2, tmp3, tmp4, result);
+  assert_different_registers(ftmp1, ftmp2, ftmp3);
+
+  // Check if cnt >= 8 (= 16 bytes)
+  cmp(cnt, 8);
+  br(Assembler::less, false, Assembler::pn, Lslow);
+  delayed()->mov(cnt, result); // copy count
+
+  // Check for 8-byte alignment of src and dst
+  or3(src, dst, tmp1);
+  andcc(tmp1, 7, G0);
+  br(Assembler::notZero, false, Assembler::pn, Lslow);
+  delayed()->nop();
+
+  // Set mask for bshuffle instruction
+  Register mask = tmp4;
+  set(0x13579bdf, mask);
+  bmask(mask, G0, G0);
+
+  // Set mask to 0xff00 ff00 ff00 ff00 to check for non-latin1 characters
+  Assembler::sethi(0xff00fc00, mask); // mask = 0x0000 0000 ff00 fc00
+  add(mask, 0x300, mask);             // mask = 0x0000 0000 ff00 ff00
+  sllx(mask, 32, tmp1);               // tmp1 = 0xff00 ff00 0000 0000
+  or3(mask, tmp1, mask);              // mask = 0xff00 ff00 ff00 ff00
+
+  // Load first 8 bytes
+  ldx(src, 0, tmp1);
+
+  bind(Lloop);
+  // Load next 8 bytes
+  ldx(src, 8, tmp2);
+
+  // Check for non-latin1 character by testing if the most significant byte of a char is set.
+  // Although we have to move the data between integer and floating point registers, this is
+  // still faster than the corresponding VIS instructions (ford/fand/fcmpd).
+  or3(tmp1, tmp2, tmp3);
+  btst(tmp3, mask);
+  // annul zeroing if branch is not taken to preserve original count
+  brx(Assembler::notZero, true, Assembler::pn, Ldone);
+  delayed()->mov(G0, result); // 0 - failed
+
+  // Move bytes into float register
+  movxtod(tmp1, ftmp1);
+  movxtod(tmp2, ftmp2);
+
+  // Compress by copying one byte per char from ftmp1 and ftmp2 to ftmp3
+  bshuffle(ftmp1, ftmp2, ftmp3);
+  stf(FloatRegisterImpl::D, ftmp3, dst, 0);
+
+  // Increment addresses and decrement count
+  inc(src, 16);
+  inc(dst, 8);
+  dec(cnt, 8);
+
+  cmp(cnt, 8);
+  // annul LDX if branch is not taken to prevent access past end of string
+  br(Assembler::greaterEqual, true, Assembler::pt, Lloop);
+  delayed()->ldx(src, 0, tmp1);
+
+  // Fallback to slow version
+  bind(Lslow);
+}
+
+// Compress char[] to byte[]. Return 0 on failure.
+void MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register result, Register tmp, Label& Ldone) {
+  Label Lloop;
+  assert_different_registers(src, dst, cnt, tmp, result);
+
+  lduh(src, 0, tmp);
+
+  bind(Lloop);
+  inc(src, sizeof(jchar));
+  cmp(tmp, 0xff);
+  // annul zeroing if branch is not taken to preserve original count
+  br(Assembler::greater, true, Assembler::pn, Ldone); // don't check xcc
+  delayed()->mov(G0, result); // 0 - failed
+  deccc(cnt);
+  stb(tmp, dst, 0);
+  inc(dst);
+  // annul LDUH if branch is not taken to prevent access past end of string
+  br(Assembler::notZero, true, Assembler::pt, Lloop);
+  delayed()->lduh(src, 0, tmp); // hoisted
+}
+
+// Inflate byte[] to char[] by inflating 16 bytes at once.
+void MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt, Register tmp,
+                                       FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone) {
+  Label Lloop, Lslow;
+  assert(UseVIS >= 3, "VIS3 is required");
+  assert_different_registers(src, dst, cnt, tmp);
+  assert_different_registers(ftmp1, ftmp2, ftmp3, ftmp4);
+
+  // Check if cnt >= 8 (= 16 bytes)
+  cmp(cnt, 8);
+  br(Assembler::less, false, Assembler::pn, Lslow);
+  delayed()->nop();
+
+  // Check for 8-byte alignment of src and dst
+  or3(src, dst, tmp);
+  andcc(tmp, 7, G0);
+  br(Assembler::notZero, false, Assembler::pn, Lslow);
+  // Initialize float register to zero
+  FloatRegister zerof = ftmp4;
+  delayed()->fzero(FloatRegisterImpl::D, zerof);
+
+  // Load first 8 bytes
+  ldf(FloatRegisterImpl::D, src, 0, ftmp1);
+
+  bind(Lloop);
+  inc(src, 8);
+  dec(cnt, 8);
+
+  // Inflate the string by interleaving each byte from the source array
+  // with a zero byte and storing the result in the destination array.
+  fpmerge(zerof, ftmp1->successor(), ftmp2);
+  stf(FloatRegisterImpl::D, ftmp2, dst, 8);
+  fpmerge(zerof, ftmp1, ftmp3);
+  stf(FloatRegisterImpl::D, ftmp3, dst, 0);
+
+  inc(dst, 16);
+
+  cmp(cnt, 8);
+  // annul LDX if branch is not taken to prevent access past end of string
+  br(Assembler::greaterEqual, true, Assembler::pt, Lloop);
+  delayed()->ldf(FloatRegisterImpl::D, src, 0, ftmp1);
+
+  // Fallback to slow version
+  bind(Lslow);
+}
+
+// Inflate byte[] to char[].
+void MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone) {
+  Label Loop;
+  assert_different_registers(src, dst, cnt, tmp);
+
+  ldub(src, 0, tmp);
+  bind(Loop);
+  inc(src);
+  deccc(cnt);
+  sth(tmp, dst, 0);
+  inc(dst, sizeof(jchar));
+  // annul LDUB if branch is not taken to prevent access past end of string
+  br(Assembler::notZero, true, Assembler::pt, Loop);
+  delayed()->ldub(src, 0, tmp); // hoisted
+}
+
+void MacroAssembler::string_compare(Register str1, Register str2,
+                                    Register cnt1, Register cnt2,
+                                    Register tmp1, Register tmp2,
+                                    Register result, int ae) {
+  Label Ldone, Lloop;
+  assert_different_registers(str1, str2, cnt1, cnt2, tmp1, result);
+  int stride1, stride2;
+
+  // Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a)
+  // we interchange str1 and str2 in the UL case and negate the result.
+  // Like this, str1 is always latin1 encoded, expect for the UU case.
+
+  if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
+    srl(cnt2, 1, cnt2);
+  }
+
+  // See if the lengths are different, and calculate min in cnt1.
+  // Save diff in case we need it for a tie-breaker.
+  Label Lskip;
+  Register diff = tmp1;
+  subcc(cnt1, cnt2, diff);
+  br(Assembler::greater, true, Assembler::pt, Lskip);
+  // cnt2 is shorter, so use its count:
+  delayed()->mov(cnt2, cnt1);
+  bind(Lskip);
+
+  // Rename registers
+  Register limit1 = cnt1;
+  Register limit2 = limit1;
+  Register chr1   = result;
+  Register chr2   = cnt2;
+  if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
+    // We need an additional register to keep track of two limits
+    assert_different_registers(str1, str2, cnt1, cnt2, tmp1, tmp2, result);
+    limit2 = tmp2;
+  }
+
+  // Is the minimum length zero?
+  cmp(limit1, (int)0); // use cast to resolve overloading ambiguity
+  br(Assembler::equal, true, Assembler::pn, Ldone);
+  // result is difference in lengths
+  if (ae == StrIntrinsicNode::UU) {
+    delayed()->sra(diff, 1, result);  // Divide by 2 to get number of chars
+  } else {
+    delayed()->mov(diff, result);
+  }
+
+  // Load first characters
+  if (ae == StrIntrinsicNode::LL) {
+    stride1 = stride2 = sizeof(jbyte);
+    ldub(str1, 0, chr1);
+    ldub(str2, 0, chr2);
+  } else if (ae == StrIntrinsicNode::UU) {
+    stride1 = stride2 = sizeof(jchar);
+    lduh(str1, 0, chr1);
+    lduh(str2, 0, chr2);
+  } else {
+    stride1 = sizeof(jbyte);
+    stride2 = sizeof(jchar);
+    ldub(str1, 0, chr1);
+    lduh(str2, 0, chr2);
+  }
+
+  // Compare first characters
+  subcc(chr1, chr2, chr1);
+  br(Assembler::notZero, false, Assembler::pt, Ldone);
+  assert(chr1 == result, "result must be pre-placed");
+  delayed()->nop();
+
+  // Check if the strings start at same location
+  cmp(str1, str2);
+  brx(Assembler::equal, true, Assembler::pn, Ldone);
+  delayed()->mov(G0, result);  // result is zero
+
+  // We have no guarantee that on 64 bit the higher half of limit is 0
+  signx(limit1);
+
+  // Get limit
+  if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
+    sll(limit1, 1, limit2);
+    subcc(limit2, stride2, chr2);
+  }
+  subcc(limit1, stride1, chr1);
+  br(Assembler::zero, true, Assembler::pn, Ldone);
+  // result is difference in lengths
+  if (ae == StrIntrinsicNode::UU) {
+    delayed()->sra(diff, 1, result);  // Divide by 2 to get number of chars
+  } else {
+    delayed()->mov(diff, result);
+  }
+
+  // Shift str1 and str2 to the end of the arrays, negate limit
+  add(str1, limit1, str1);
+  add(str2, limit2, str2);
+  neg(chr1, limit1);  // limit1 = -(limit1-stride1)
+  if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
+    neg(chr2, limit2);  // limit2 = -(limit2-stride2)
+  }
+
+  // Compare the rest of the characters
+  if (ae == StrIntrinsicNode::UU) {
+    lduh(str1, limit1, chr1);
+  } else {
+    ldub(str1, limit1, chr1);
+  }
+
+  bind(Lloop);
+  if (ae == StrIntrinsicNode::LL) {
+    ldub(str2, limit2, chr2);
+  } else {
+    lduh(str2, limit2, chr2);
+  }
+
+  subcc(chr1, chr2, chr1);
+  br(Assembler::notZero, false, Assembler::pt, Ldone);
+  assert(chr1 == result, "result must be pre-placed");
+  delayed()->inccc(limit1, stride1);
+  if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
+    inccc(limit2, stride2);
+  }
+
+  // annul LDUB if branch is not taken to prevent access past end of string
+  br(Assembler::notZero, true, Assembler::pt, Lloop);
+  if (ae == StrIntrinsicNode::UU) {
+    delayed()->lduh(str1, limit2, chr1);
+  } else {
+    delayed()->ldub(str1, limit1, chr1);
+  }
+
+  // If strings are equal up to min length, return the length difference.
+  if (ae == StrIntrinsicNode::UU) {
+    // Divide by 2 to get number of chars
+    sra(diff, 1, result);
+  } else {
+    mov(diff, result);
+  }
+
+  // Otherwise, return the difference between the first mismatched chars.
+  bind(Ldone);
+  if(ae == StrIntrinsicNode::UL) {
+    // Negate result (see note above)
+    neg(result);
+  }
+}
+
+void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
+                                  Register limit, Register tmp, Register result, bool is_byte) {
+  Label Ldone, Lvector, Lloop;
+  assert_different_registers(ary1, ary2, limit, tmp, result);
+
+  int length_offset  = arrayOopDesc::length_offset_in_bytes();
+  int base_offset    = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
+
+  if (is_array_equ) {
+    // return true if the same array
+    cmp(ary1, ary2);
+    brx(Assembler::equal, true, Assembler::pn, Ldone);
+    delayed()->add(G0, 1, result); // equal
+
+    br_null(ary1, true, Assembler::pn, Ldone);
+    delayed()->mov(G0, result);    // not equal
+
+    br_null(ary2, true, Assembler::pn, Ldone);
+    delayed()->mov(G0, result);    // not equal
+
+    // load the lengths of arrays
+    ld(Address(ary1, length_offset), limit);
+    ld(Address(ary2, length_offset), tmp);
+
+    // return false if the two arrays are not equal length
+    cmp(limit, tmp);
+    br(Assembler::notEqual, true, Assembler::pn, Ldone);
+    delayed()->mov(G0, result);    // not equal
+  }
+
+  cmp_zero_and_br(Assembler::zero, limit, Ldone, true, Assembler::pn);
+  delayed()->add(G0, 1, result); // zero-length arrays are equal
+
+  if (is_array_equ) {
+    // load array addresses
+    add(ary1, base_offset, ary1);
+    add(ary2, base_offset, ary2);
+  } else {
+    // We have no guarantee that on 64 bit the higher half of limit is 0
+    signx(limit);
+  }
+
+  if (is_byte) {
+    Label Lskip;
+    // check for trailing byte
+    andcc(limit, 0x1, tmp);
+    br(Assembler::zero, false, Assembler::pt, Lskip);
+    delayed()->nop();
+
+    // compare the trailing byte
+    sub(limit, sizeof(jbyte), limit);
+    ldub(ary1, limit, result);
+    ldub(ary2, limit, tmp);
+    cmp(result, tmp);
+    br(Assembler::notEqual, true, Assembler::pt, Ldone);
+    delayed()->mov(G0, result);    // not equal
+
+    // only one byte?
+    cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn);
+    delayed()->add(G0, 1, result); // zero-length arrays are equal
+    bind(Lskip);
+  } else if (is_array_equ) {
+    // set byte count
+    sll(limit, exact_log2(sizeof(jchar)), limit);
+  }
+
+  // check for trailing character
+  andcc(limit, 0x2, tmp);
   br(Assembler::zero, false, Assembler::pt, Lvector);
   delayed()->nop();
 
   // compare the trailing char
   sub(limit, sizeof(jchar), limit);
-  lduh(ary1, limit, chr1);
-  lduh(ary2, limit, chr2);
-  cmp(chr1, chr2);
+  lduh(ary1, limit, result);
+  lduh(ary2, limit, tmp);
+  cmp(result, tmp);
   br(Assembler::notEqual, true, Assembler::pt, Ldone);
   delayed()->mov(G0, result);     // not equal
 
-  // only one char ?
+  // only one char?
   cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn);
   delayed()->add(G0, 1, result); // zero-length arrays are equal
 
@@ -4284,21 +4645,23 @@
   add(ary2, limit, ary2);
   neg(limit, limit);
 
-  lduw(ary1, limit, chr1);
+  lduw(ary1, limit, result);
   bind(Lloop);
-  lduw(ary2, limit, chr2);
-  cmp(chr1, chr2);
+  lduw(ary2, limit, tmp);
+  cmp(result, tmp);
   br(Assembler::notEqual, true, Assembler::pt, Ldone);
   delayed()->mov(G0, result);     // not equal
   inccc(limit, 2*sizeof(jchar));
   // annul LDUW if branch is not taken to prevent access past end of array
   br(Assembler::notZero, true, Assembler::pt, Lloop);
-  delayed()->lduw(ary1, limit, chr1); // hoisted
-
-  // Caller should set it:
-  // add(G0, 1, result); // equals
+  delayed()->lduw(ary1, limit, result); // hoisted
+
+  add(G0, 1, result); // equals
+  bind(Ldone);
 }
 
+#endif
+
 // Use BIS for zeroing (count is in bytes).
 void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) {
   assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing");
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1433,10 +1433,31 @@
   void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2);
   void inc_counter(int*    counter_addr, Register Rtmp1, Register Rtmp2);
 
-  // Compare char[] arrays aligned to 4 bytes.
-  void char_arrays_equals(Register ary1, Register ary2,
-                          Register limit, Register result,
-                          Register chr1, Register chr2, Label& Ldone);
+#ifdef COMPILER2
+  // Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure.
+  void string_compress_16(Register src, Register dst, Register cnt, Register result,
+                          Register tmp1, Register tmp2, Register tmp3, Register tmp4,
+                          FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone);
+
+  // Compress char[] to byte[]. Return 0 on failure.
+  void string_compress(Register src, Register dst, Register cnt, Register tmp, Register result, Label& Ldone);
+
+  // Inflate byte[] to char[] by inflating 16 bytes at once.
+  void string_inflate_16(Register src, Register dst, Register cnt, Register tmp,
+                         FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone);
+
+  // Inflate byte[] to char[].
+  void string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone);
+
+  void string_compare(Register str1, Register str2,
+                      Register cnt1, Register cnt2,
+                      Register tmp1, Register tmp2,
+                      Register result, int ae);
+
+  void array_equals(bool is_array_equ, Register ary1, Register ary2,
+                    Register limit, Register tmp, Register result, bool is_byte);
+#endif
+
   // Use BIS for zeroing
   void bis_zeroing(Register to, Register count, Register temp, Label& Ldone);
 
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -69,7 +69,7 @@
                                  Register obj_reg, SystemDictionary::WKID klass_id,
                                  Register temp_reg, Register temp2_reg,
                                  const char* error_message) {
-  Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
+  InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
   KlassHandle klass = SystemDictionary::well_known_klass(klass_id);
   bool did_save = false;
   if (temp_reg == noreg || temp2_reg == noreg) {
--- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -417,6 +417,67 @@
 
 //-------------------------------------------------------------------
 
+void NativeMovConstReg32::verify() {
+  NativeInstruction::verify();
+  // make sure code pattern is actually a "set_metadata" synthetic instruction
+  // see MacroAssembler::set_oop()
+  int i0 = long_at(sethi_offset);
+  int i1 = long_at(add_offset);
+
+  // verify the pattern "sethi %hi22(imm), reg ;  add reg, %lo10(imm), reg"
+  Register rd = inv_rd(i0);
+  if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) {
+    fatal("not a set_metadata");
+  }
+}
+
+
+void NativeMovConstReg32::print() {
+  tty->print_cr(INTPTR_FORMAT ": mov reg, " INTPTR_FORMAT, instruction_address(), data());
+}
+
+
+intptr_t NativeMovConstReg32::data() const {
+  return data32(long_at(sethi_offset), long_at(add_offset));
+}
+
+
+void NativeMovConstReg32::set_data(intptr_t x) {
+  set_long_at(sethi_offset, set_data32_sethi(  long_at(sethi_offset), x));
+  set_long_at(add_offset,   set_data32_simm13( long_at(add_offset),   x));
+
+  // also store the value into an oop_Relocation cell, if any
+  CodeBlob* cb = CodeCache::find_blob(instruction_address());
+  nmethod*  nm = cb ? cb->as_nmethod_or_null() : NULL;
+  if (nm != NULL) {
+    RelocIterator iter(nm, instruction_address(), next_instruction_address());
+    oop* oop_addr = NULL;
+    Metadata** metadata_addr = NULL;
+    while (iter.next()) {
+      if (iter.type() == relocInfo::oop_type) {
+        oop_Relocation *r = iter.oop_reloc();
+        if (oop_addr == NULL) {
+          oop_addr = r->oop_addr();
+          *oop_addr = cast_to_oop(x);
+        } else {
+          assert(oop_addr == r->oop_addr(), "must be only one set-oop here");
+        }
+      }
+      if (iter.type() == relocInfo::metadata_type) {
+        metadata_Relocation *r = iter.metadata_reloc();
+        if (metadata_addr == NULL) {
+          metadata_addr = r->metadata_addr();
+          *metadata_addr = (Metadata*)x;
+        } else {
+          assert(metadata_addr == r->metadata_addr(), "must be only one set-metadata here");
+        }
+      }
+    }
+  }
+}
+
+//-------------------------------------------------------------------
+
 void NativeMovConstRegPatching::verify() {
   NativeInstruction::verify();
   // Make sure code pattern is sethi/nop/add.
--- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -518,6 +518,46 @@
 
 #endif // _LP64
 
+// An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions
+// (used to manipulate inlined data references, etc.)
+//      set_metadata imm, reg
+//      == sethi %hi22(imm), reg ;  add reg, %lo10(imm), reg
+class NativeMovConstReg32;
+inline NativeMovConstReg32* nativeMovConstReg32_at(address address);
+class NativeMovConstReg32: public NativeInstruction {
+ public:
+  enum Sparc_specific_constants {
+    sethi_offset           = 0,
+    add_offset             = 4,
+    instruction_size       = 8
+  };
+
+  address instruction_address() const       { return addr_at(0); }
+  address next_instruction_address() const  { return addr_at(instruction_size); }
+
+  // (The [set_]data accessor respects oop_type relocs also.)
+  intptr_t data() const;
+  void set_data(intptr_t x);
+
+  // report the destination register
+  Register destination() { return inv_rd(long_at(sethi_offset)); }
+
+  void  verify();
+  void  print();
+
+  // unit test stuff
+  static void test();
+
+  // Creation
+  friend inline NativeMovConstReg32* nativeMovConstReg32_at(address address) {
+    NativeMovConstReg32* test = (NativeMovConstReg32*)address;
+    #ifdef ASSERT
+      test->verify();
+    #endif
+    return test;
+  }
+};
+
 // An interface for accessing/manipulating native set_metadata imm, reg instructions.
 // (used to manipulate inlined data references, etc.)
 //      set_metadata imm, reg
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1955,7 +1955,7 @@
 //    return to caller
 //
 nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
-                                                methodHandle method,
+                                                const methodHandle& method,
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Jul 05 21:00:20 2017 +0200
@@ -2905,232 +2905,6 @@
     __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst);
   %}
 
-
-  enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{
-    Label Ldone, Lloop;
-    MacroAssembler _masm(&cbuf);
-
-    Register   str1_reg = reg_to_register_object($str1$$reg);
-    Register   str2_reg = reg_to_register_object($str2$$reg);
-    Register   cnt1_reg = reg_to_register_object($cnt1$$reg);
-    Register   cnt2_reg = reg_to_register_object($cnt2$$reg);
-    Register result_reg = reg_to_register_object($result$$reg);
-
-    assert(result_reg != str1_reg &&
-           result_reg != str2_reg &&
-           result_reg != cnt1_reg &&
-           result_reg != cnt2_reg ,
-           "need different registers");
-
-    // Compute the minimum of the string lengths(str1_reg) and the
-    // difference of the string lengths (stack)
-
-    // See if the lengths are different, and calculate min in str1_reg.
-    // Stash diff in O7 in case we need it for a tie-breaker.
-    Label Lskip;
-    __ subcc(cnt1_reg, cnt2_reg, O7);
-    __ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
-    __ br(Assembler::greater, true, Assembler::pt, Lskip);
-    // cnt2 is shorter, so use its count:
-    __ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
-    __ bind(Lskip);
-
-    // reallocate cnt1_reg, cnt2_reg, result_reg
-    // Note:  limit_reg holds the string length pre-scaled by 2
-    Register limit_reg =   cnt1_reg;
-    Register  chr2_reg =   cnt2_reg;
-    Register  chr1_reg = result_reg;
-    // str{12} are the base pointers
-
-    // Is the minimum length zero?
-    __ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity
-    __ br(Assembler::equal, true, Assembler::pn, Ldone);
-    __ delayed()->mov(O7, result_reg);  // result is difference in lengths
-
-    // Load first characters
-    __ lduh(str1_reg, 0, chr1_reg);
-    __ lduh(str2_reg, 0, chr2_reg);
-
-    // Compare first characters
-    __ subcc(chr1_reg, chr2_reg, chr1_reg);
-    __ br(Assembler::notZero, false, Assembler::pt,  Ldone);
-    assert(chr1_reg == result_reg, "result must be pre-placed");
-    __ delayed()->nop();
-
-    {
-      // Check after comparing first character to see if strings are equivalent
-      Label LSkip2;
-      // Check if the strings start at same location
-      __ cmp(str1_reg, str2_reg);
-      __ brx(Assembler::notEqual, true, Assembler::pt, LSkip2);
-      __ delayed()->nop();
-
-      // Check if the length difference is zero (in O7)
-      __ cmp(G0, O7);
-      __ br(Assembler::equal, true, Assembler::pn, Ldone);
-      __ delayed()->mov(G0, result_reg);  // result is zero
-
-      // Strings might not be equal
-      __ bind(LSkip2);
-    }
-
-    // We have no guarantee that on 64 bit the higher half of limit_reg is 0
-    __ signx(limit_reg);
-
-    __ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg);
-    __ br(Assembler::equal, true, Assembler::pn, Ldone);
-    __ delayed()->mov(O7, result_reg);  // result is difference in lengths
-
-    // Shift str1_reg and str2_reg to the end of the arrays, negate limit
-    __ add(str1_reg, limit_reg, str1_reg);
-    __ add(str2_reg, limit_reg, str2_reg);
-    __ neg(chr1_reg, limit_reg);  // limit = -(limit-2)
-
-    // Compare the rest of the characters
-    __ lduh(str1_reg, limit_reg, chr1_reg);
-    __ bind(Lloop);
-    // __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted
-    __ lduh(str2_reg, limit_reg, chr2_reg);
-    __ subcc(chr1_reg, chr2_reg, chr1_reg);
-    __ br(Assembler::notZero, false, Assembler::pt, Ldone);
-    assert(chr1_reg == result_reg, "result must be pre-placed");
-    __ delayed()->inccc(limit_reg, sizeof(jchar));
-    // annul LDUH if branch is not taken to prevent access past end of string
-    __ br(Assembler::notZero, true, Assembler::pt, Lloop);
-    __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
-
-    // If strings are equal up to min length, return the length difference.
-    __ mov(O7, result_reg);
-
-    // Otherwise, return the difference between the first mismatched chars.
-    __ bind(Ldone);
-  %}
-
-enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{
-    Label Lchar, Lchar_loop, Ldone;
-    MacroAssembler _masm(&cbuf);
-
-    Register   str1_reg = reg_to_register_object($str1$$reg);
-    Register   str2_reg = reg_to_register_object($str2$$reg);
-    Register    cnt_reg = reg_to_register_object($cnt$$reg);
-    Register   tmp1_reg = O7;
-    Register result_reg = reg_to_register_object($result$$reg);
-
-    assert(result_reg != str1_reg &&
-           result_reg != str2_reg &&
-           result_reg !=  cnt_reg &&
-           result_reg != tmp1_reg ,
-           "need different registers");
-
-    __ cmp(str1_reg, str2_reg); //same char[] ?
-    __ brx(Assembler::equal, true, Assembler::pn, Ldone);
-    __ delayed()->add(G0, 1, result_reg);
-
-    __ cmp_zero_and_br(Assembler::zero, cnt_reg, Ldone, true, Assembler::pn);
-    __ delayed()->add(G0, 1, result_reg); // count == 0
-
-    //rename registers
-    Register limit_reg =    cnt_reg;
-    Register  chr1_reg = result_reg;
-    Register  chr2_reg =   tmp1_reg;
-
-    // We have no guarantee that on 64 bit the higher half of limit_reg is 0
-    __ signx(limit_reg);
-
-    //check for alignment and position the pointers to the ends
-    __ or3(str1_reg, str2_reg, chr1_reg);
-    __ andcc(chr1_reg, 0x3, chr1_reg);
-    // notZero means at least one not 4-byte aligned.
-    // We could optimize the case when both arrays are not aligned
-    // but it is not frequent case and it requires additional checks.
-    __ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare
-    __ delayed()->sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); // set byte count
-
-    // Compare char[] arrays aligned to 4 bytes.
-    __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
-                          chr1_reg, chr2_reg, Ldone);
-    __ ba(Ldone);
-    __ delayed()->add(G0, 1, result_reg);
-
-    // char by char compare
-    __ bind(Lchar);
-    __ add(str1_reg, limit_reg, str1_reg);
-    __ add(str2_reg, limit_reg, str2_reg);
-    __ neg(limit_reg); //negate count
-
-    __ lduh(str1_reg, limit_reg, chr1_reg);
-    // Lchar_loop
-    __ bind(Lchar_loop);
-    __ lduh(str2_reg, limit_reg, chr2_reg);
-    __ cmp(chr1_reg, chr2_reg);
-    __ br(Assembler::notEqual, true, Assembler::pt, Ldone);
-    __ delayed()->mov(G0, result_reg); //not equal
-    __ inccc(limit_reg, sizeof(jchar));
-    // annul LDUH if branch is not taken to prevent access past end of string
-    __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop);
-    __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
-
-    __ add(G0, 1, result_reg);  //equal
-
-    __ bind(Ldone);
-  %}
-
-enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI result) %{
-    Label Lvector, Ldone, Lloop;
-    MacroAssembler _masm(&cbuf);
-
-    Register   ary1_reg = reg_to_register_object($ary1$$reg);
-    Register   ary2_reg = reg_to_register_object($ary2$$reg);
-    Register   tmp1_reg = reg_to_register_object($tmp1$$reg);
-    Register   tmp2_reg = O7;
-    Register result_reg = reg_to_register_object($result$$reg);
-
-    int length_offset  = arrayOopDesc::length_offset_in_bytes();
-    int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
-
-    // return true if the same array
-    __ cmp(ary1_reg, ary2_reg);
-    __ brx(Assembler::equal, true, Assembler::pn, Ldone);
-    __ delayed()->add(G0, 1, result_reg); // equal
-
-    __ br_null(ary1_reg, true, Assembler::pn, Ldone);
-    __ delayed()->mov(G0, result_reg);    // not equal
-
-    __ br_null(ary2_reg, true, Assembler::pn, Ldone);
-    __ delayed()->mov(G0, result_reg);    // not equal
-
-    //load the lengths of arrays
-    __ ld(Address(ary1_reg, length_offset), tmp1_reg);
-    __ ld(Address(ary2_reg, length_offset), tmp2_reg);
-
-    // return false if the two arrays are not equal length
-    __ cmp(tmp1_reg, tmp2_reg);
-    __ br(Assembler::notEqual, true, Assembler::pn, Ldone);
-    __ delayed()->mov(G0, result_reg);     // not equal
-
-    __ cmp_zero_and_br(Assembler::zero, tmp1_reg, Ldone, true, Assembler::pn);
-    __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
-
-    // load array addresses
-    __ add(ary1_reg, base_offset, ary1_reg);
-    __ add(ary2_reg, base_offset, ary2_reg);
-
-    // renaming registers
-    Register chr1_reg  =  result_reg; // for characters in ary1
-    Register chr2_reg  =  tmp2_reg;   // for characters in ary2
-    Register limit_reg =  tmp1_reg;   // length
-
-    // set byte count
-    __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg);
-
-    // Compare char[] arrays aligned to 4 bytes.
-    __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
-                          chr1_reg, chr2_reg, Ldone);
-    __ add(G0, 1, result_reg); // equals
-
-    __ bind(Ldone);
-  %}
-
   enc_class enc_rethrow() %{
     cbuf.set_insts_mark();
     Register temp_reg = G3;
@@ -10275,33 +10049,204 @@
   ins_pipe(long_memory_op);
 %}
 
-instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
-                        o7RegI tmp, flagsReg ccr) %{
+instruct string_compareL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
+                         o7RegI tmp, flagsReg ccr) %{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
+  ins_cost(300);
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp" %}
+  ins_encode %{
+    __ string_compare($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register, 
+                      $tmp$$Register, $tmp$$Register,
+                      $result$$Register, StrIntrinsicNode::LL);
+  %}                    
+  ins_pipe(long_memory_op);
+%}
+
+instruct string_compareU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
+                         o7RegI tmp, flagsReg ccr) %{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
   match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
   effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
   ins_cost(300);
-  format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp" %}
-  ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) );
+  format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp" %}
+  ins_encode %{
+    __ string_compare($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register,
+                      $tmp$$Register, $tmp$$Register,
+                      $result$$Register, StrIntrinsicNode::UU);
+  %}                    
   ins_pipe(long_memory_op);
 %}
 
-instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
-                       o7RegI tmp, flagsReg ccr) %{
+instruct string_compareLU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
+                          o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2);
+  ins_cost(300);
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1,$tmp2" %}
+  ins_encode %{
+    __ string_compare($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register,
+                      $tmp1$$Register, $tmp2$$Register,
+                      $result$$Register, StrIntrinsicNode::LU);
+  %}                    
+  ins_pipe(long_memory_op);
+%}
+
+instruct string_compareUL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
+                          o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2);
+  ins_cost(300);
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1,$tmp2" %}
+  ins_encode %{
+    __ string_compare($str2$$Register, $str1$$Register,
+                      $cnt2$$Register, $cnt1$$Register, 
+                      $tmp1$$Register, $tmp2$$Register,
+                      $result$$Register, StrIntrinsicNode::UL);
+  %}                    
+  ins_pipe(long_memory_op);
+%}
+
+instruct string_equalsL(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
+                        o7RegI tmp, flagsReg ccr) %{
+  predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL);
   match(Set result (StrEquals (Binary str1 str2) cnt));
   effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr);
   ins_cost(300);
-  format %{ "String Equals $str1,$str2,$cnt -> $result   // KILL $tmp" %}
-  ins_encode( enc_String_Equals(str1, str2, cnt, result) );
+  format %{ "String Equals byte[] $str1,$str2,$cnt -> $result   // KILL $tmp" %}
+  ins_encode %{
+    __ array_equals(false, $str1$$Register, $str2$$Register,
+                    $cnt$$Register, $tmp$$Register,
+                    $result$$Register, true /* byte */);
+  %}
   ins_pipe(long_memory_op);
 %}
 
-instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result,
-                      o7RegI tmp2, flagsReg ccr) %{
+instruct string_equalsU(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
+                        o7RegI tmp, flagsReg ccr) %{
+  predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU);
+  match(Set result (StrEquals (Binary str1 str2) cnt));
+  effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr);
+  ins_cost(300);
+  format %{ "String Equals char[]  $str1,$str2,$cnt -> $result   // KILL $tmp" %}
+  ins_encode %{
+    __ array_equals(false, $str1$$Register, $str2$$Register,
+                    $cnt$$Register, $tmp$$Register,
+                    $result$$Register, false /* byte */);
+  %}
+  ins_pipe(long_memory_op);
+%}
+
+instruct array_equalsB(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result,
+                       o7RegI tmp2, flagsReg ccr) %{
+  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
   match(Set result (AryEq ary1 ary2));
   effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
   ins_cost(300);
   format %{ "Array Equals $ary1,$ary2 -> $result   // KILL $tmp1,$tmp2" %}
-  ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result));
+  ins_encode %{
+    __ array_equals(true, $ary1$$Register, $ary2$$Register,
+                    $tmp1$$Register, $tmp2$$Register,
+                    $result$$Register, true /* byte */);
+  %}
+  ins_pipe(long_memory_op);
+%}
+
+instruct array_equalsC(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result,
+                       o7RegI tmp2, flagsReg ccr) %{
+  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
+  match(Set result (AryEq ary1 ary2));
+  effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
+  ins_cost(300);
+  format %{ "Array Equals $ary1,$ary2 -> $result   // KILL $tmp1,$tmp2" %}
+  ins_encode %{
+    __ array_equals(true, $ary1$$Register, $ary2$$Register,
+                    $tmp1$$Register, $tmp2$$Register,
+                    $result$$Register, false /* byte */);
+  %}
+  ins_pipe(long_memory_op);
+%}
+
+// char[] to byte[] compression
+instruct string_compress(o0RegP src, o1RegP dst, g3RegI len, notemp_iRegI result, iRegL tmp, flagsReg ccr) %{
+  predicate(UseVIS < 3);
+  match(Set result (StrCompressedCopy src (Binary dst len)));
+  effect(TEMP result, TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr);
+  ins_cost(300);
+  format %{ "String Compress $src,$dst,$len -> $result    // KILL $tmp" %}
+  ins_encode %{
+    Label Ldone;
+    __ signx($len$$Register);
+    __ cmp_zero_and_br(Assembler::zero, $len$$Register, Ldone, false, Assembler::pn);
+    __ delayed()->mov($len$$Register, $result$$Register); // copy count
+    __ string_compress($src$$Register, $dst$$Register, $len$$Register, $result$$Register, $tmp$$Register, Ldone);
+    __ bind(Ldone);
+  %}
+  ins_pipe(long_memory_op);
+%}
+
+// fast char[] to byte[] compression using VIS instructions
+instruct string_compress_fast(o0RegP src, o1RegP dst, g3RegI len, notemp_iRegI result,
+                              iRegL tmp1, iRegL tmp2, iRegL tmp3, iRegL tmp4,
+                              regD ftmp1, regD ftmp2, regD ftmp3, flagsReg ccr) %{
+  predicate(UseVIS >= 3);
+  match(Set result (StrCompressedCopy src (Binary dst len)));
+  effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ftmp1, TEMP ftmp2, TEMP ftmp3, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr);
+  ins_cost(300);
+  format %{ "String Compress Fast $src,$dst,$len -> $result    // KILL $tmp1,$tmp2,$tmp3,$tmp4,$ftmp1,$ftmp2,$ftmp3" %}
+  ins_encode %{
+    Label Ldone;
+    __ signx($len$$Register);
+    __ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $result$$Register,
+                          $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register,
+                          $ftmp1$$FloatRegister, $ftmp2$$FloatRegister, $ftmp3$$FloatRegister, Ldone);
+    __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone);
+    __ string_compress($src$$Register, $dst$$Register, $len$$Register, $result$$Register, $tmp1$$Register, Ldone);
+    __ bind(Ldone);
+  %}
+  ins_pipe(long_memory_op);
+%}
+
+// byte[] to char[] inflation
+instruct string_inflate(Universe dummy, o0RegP src, o1RegP dst, g3RegI len,
+                        iRegL tmp, flagsReg ccr) %{
+  match(Set dummy (StrInflatedCopy src (Binary dst len)));
+  effect(TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr);
+  ins_cost(300);
+  format %{ "String Inflate $src,$dst,$len    // KILL $tmp" %}
+  ins_encode %{
+    Label Ldone;
+    __ signx($len$$Register);
+    __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone);
+    __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, Ldone);
+    __ bind(Ldone);
+  %}
+  ins_pipe(long_memory_op);
+%}
+
+// fast byte[] to char[] inflation using VIS instructions
+instruct string_inflate_fast(Universe dummy, o0RegP src, o1RegP dst, g3RegI len,
+                             iRegL tmp, regD ftmp1, regD ftmp2, regD ftmp3, regD ftmp4, flagsReg ccr) %{
+  predicate(UseVIS >= 3);
+  match(Set dummy (StrInflatedCopy src (Binary dst len)));
+  effect(TEMP tmp, TEMP ftmp1, TEMP ftmp2, TEMP ftmp3, TEMP ftmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr);
+  ins_cost(300);
+  format %{ "String Inflate Fast $src,$dst,$len    // KILL $tmp,$ftmp1,$ftmp2,$ftmp3,$ftmp4" %}
+  ins_encode %{
+    Label Ldone;
+    __ signx($len$$Register);
+    __ string_inflate_16($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register,
+                         $ftmp1$$FloatRegister, $ftmp2$$FloatRegister, $ftmp3$$FloatRegister, $ftmp4$$FloatRegister, Ldone);
+    __ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone);
+    __ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, Ldone);
+    __ bind(Ldone);
+  %}
   ins_pipe(long_memory_op);
 %}
 
--- a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -83,7 +83,26 @@
   declare_constant(VM_Version::vis1_instructions_m)                       \
   declare_constant(VM_Version::vis2_instructions_m)                       \
   declare_constant(VM_Version::vis3_instructions_m)                       \
-  declare_constant(VM_Version::cbcond_instructions_m)
+  declare_constant(VM_Version::cbcond_instructions_m)                     \
+  declare_constant(VM_Version::v8_instructions_m)                         \
+  declare_constant(VM_Version::hardware_mul32_m)                          \
+  declare_constant(VM_Version::hardware_div32_m)                          \
+  declare_constant(VM_Version::hardware_fsmuld_m)                         \
+  declare_constant(VM_Version::hardware_popc_m)                           \
+  declare_constant(VM_Version::v9_instructions_m)                         \
+  declare_constant(VM_Version::sun4v_m)                                   \
+  declare_constant(VM_Version::blk_init_instructions_m)                   \
+  declare_constant(VM_Version::fmaf_instructions_m)                       \
+  declare_constant(VM_Version::fmau_instructions_m)                       \
+  declare_constant(VM_Version::sparc64_family_m)                          \
+  declare_constant(VM_Version::M_family_m)                                \
+  declare_constant(VM_Version::T_family_m)                                \
+  declare_constant(VM_Version::T1_model_m)                                \
+  declare_constant(VM_Version::sparc5_instructions_m)                     \
+  declare_constant(VM_Version::aes_instructions_m)                        \
+  declare_constant(VM_Version::sha1_instruction_m)                        \
+  declare_constant(VM_Version::sha256_instruction_m)                      \
+  declare_constant(VM_Version::sha512_instruction_m)
 
 #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
 
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -3036,6 +3036,35 @@
   emit_int8(imm8);
 }
 
+void Assembler::pcmpeqw(XMMRegister dst, XMMRegister src) {
+  NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+  emit_simd_arith(0x75, dst, src, VEX_SIMD_66,
+                  false, (VM_Version::supports_avx512dq() == false));
+}
+
+void Assembler::vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
+  assert(UseAVX > 0, "some form of AVX must be enabled");
+  emit_vex_arith(0x75, dst, nds, src, VEX_SIMD_66, vector_len,
+                 false, (VM_Version::supports_avx512dq() == false));
+}
+
+void Assembler::pmovmskb(Register dst, XMMRegister src) {
+  assert(VM_Version::supports_sse2(), "");
+  int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F,
+                                      false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
+  emit_int8((unsigned char)0xD7);
+  emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::vpmovmskb(Register dst, XMMRegister src) {
+  assert(VM_Version::supports_avx2(), "");
+  int vector_len = AVX_256bit;
+  int encode = vex_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66,
+                                     vector_len, VEX_OPCODE_0F, true, false);
+  emit_int8((unsigned char)0xD7);
+  emit_int8((unsigned char)(0xC0 | encode));
+}
+
 void Assembler::pextrd(Register dst, XMMRegister src, int imm8) {
   assert(VM_Version::supports_sse4_1(), "");
   int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true,
@@ -3108,6 +3137,17 @@
   emit_int8((unsigned char)(0xC0 | encode));
 }
 
+void Assembler::vpmovzxbw(XMMRegister dst, Address src) {
+  assert(VM_Version::supports_avx(), "");
+  InstructionMark im(this);
+  bool vector256 = true;
+  assert(dst != xnoreg, "sanity");
+  int dst_enc = dst->encoding();
+  vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256);
+  emit_int8(0x30);
+  emit_operand(dst, src);
+}
+
 // generic
 void Assembler::pop(Register dst) {
   int encode = prefix_and_encode(dst->encoding());
@@ -5370,6 +5410,16 @@
   emit_int8((unsigned char)(0xC0 | encode));
 }
 
+// duplicate 2-bytes integer data from src into 16 locations in dest
+void Assembler::vpbroadcastw(XMMRegister dst, XMMRegister src) {
+  assert(VM_Version::supports_avx2(), "");
+  bool vector_len = AVX_256bit;
+  int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
+                                     vector_len, VEX_OPCODE_0F_38, false);
+  emit_int8(0x79);
+  emit_int8((unsigned char)(0xC0 | encode));
+}
+
 // duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
 void Assembler::evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len) {
   _instruction_uses_vl = true;
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1682,6 +1682,12 @@
   void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
   void pcmpestri(XMMRegister xmm1, Address src, int imm8);
 
+  void pcmpeqw(XMMRegister dst, XMMRegister src);
+  void vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
+
+  void pmovmskb(Register dst, XMMRegister src);
+  void vpmovmskb(Register dst, XMMRegister src);
+
   // SSE 4.1 extract
   void pextrd(Register dst, XMMRegister src, int imm8);
   void pextrq(Register dst, XMMRegister src, int imm8);
@@ -1698,6 +1704,8 @@
   void pmovzxbw(XMMRegister dst, XMMRegister src);
   void pmovzxbw(XMMRegister dst, Address src);
 
+  void vpmovzxbw(XMMRegister dst, Address src);
+
 #ifndef _LP64 // no 32bit push/pop on amd64
   void popl(Address dst);
 #endif
@@ -2116,6 +2124,9 @@
   // duplicate 4-bytes integer data from src into 8 locations in dest
   void vpbroadcastd(XMMRegister dst, XMMRegister src);
 
+  // duplicate 2-bytes integer data from src into 16 locations in dest
+  void vpbroadcastw(XMMRegister dst, XMMRegister src);
+
   // duplicate n-bytes integer data from src into vector_len locations in dest
   void evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len);
   void evpbroadcastb(XMMRegister dst, Address src, int vector_len);
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -509,86 +509,6 @@
 }
 
 
-// This is the fast version of java.lang.String.compare; it has not
-// OSR-entry and therefore, we generate a slow version for OSR's
-void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) {
-  __ movptr (rbx, rcx); // receiver is in rcx
-  __ movptr (rax, arg1->as_register());
-
-  // Get addresses of first characters from both Strings
-  __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
-  if (java_lang_String::has_offset_field()) {
-    __ movptr     (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
-    __ movl       (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
-    __ lea        (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
-  } else {
-    __ movl       (rax, Address(rsi, arrayOopDesc::length_offset_in_bytes()));
-    __ lea        (rsi, Address(rsi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
-  }
-
-  // rbx, may be NULL
-  add_debug_info_for_null_check_here(info);
-  __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
-  if (java_lang_String::has_offset_field()) {
-    __ movptr     (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
-    __ movl       (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
-    __ lea        (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
-  } else {
-    __ movl       (rbx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
-    __ lea        (rdi, Address(rdi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
-  }
-
-  // compute minimum length (in rax) and difference of lengths (on top of stack)
-  __ mov   (rcx, rbx);
-  __ subptr(rbx, rax); // subtract lengths
-  __ push  (rbx);      // result
-  __ cmov  (Assembler::lessEqual, rax, rcx);
-
-  // is minimum length 0?
-  Label noLoop, haveResult;
-  __ testptr (rax, rax);
-  __ jcc (Assembler::zero, noLoop);
-
-  // compare first characters
-  __ load_unsigned_short(rcx, Address(rdi, 0));
-  __ load_unsigned_short(rbx, Address(rsi, 0));
-  __ subl(rcx, rbx);
-  __ jcc(Assembler::notZero, haveResult);
-  // starting loop
-  __ decrement(rax); // we already tested index: skip one
-  __ jcc(Assembler::zero, noLoop);
-
-  // set rsi.edi to the end of the arrays (arrays have same length)
-  // negate the index
-
-  __ lea(rsi, Address(rsi, rax, Address::times_2, type2aelembytes(T_CHAR)));
-  __ lea(rdi, Address(rdi, rax, Address::times_2, type2aelembytes(T_CHAR)));
-  __ negptr(rax);
-
-  // compare the strings in a loop
-
-  Label loop;
-  __ align(wordSize);
-  __ bind(loop);
-  __ load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0));
-  __ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0));
-  __ subl(rcx, rbx);
-  __ jcc(Assembler::notZero, haveResult);
-  __ increment(rax);
-  __ jcc(Assembler::notZero, loop);
-
-  // strings are equal up to min length
-
-  __ bind(noLoop);
-  __ pop(rax);
-  return_op(LIR_OprFact::illegalOpr);
-
-  __ bind(haveResult);
-  // leave instruction is going to discard the TOS value
-  __ mov (rax, rcx); // result of call is in rax,
-}
-
-
 void LIR_Assembler::return_op(LIR_Opr result) {
   assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == rax, "word returns are in rax,");
   if (!result->is_illegal() && result->is_float_kind() && !result->is_xmm_register()) {
@@ -1667,8 +1587,8 @@
   Register Rtmp1 = noreg;
 
   // check if it needs to be profiled
-  ciMethodData* md;
-  ciProfileData* data;
+  ciMethodData* md = NULL;
+  ciProfileData* data = NULL;
 
   if (op->should_profile()) {
     ciMethod* method = op->profiled_method();
@@ -1827,8 +1747,8 @@
     CodeStub* stub = op->stub();
 
     // check if it needs to be profiled
-    ciMethodData* md;
-    ciProfileData* data;
+    ciMethodData* md = NULL;
+    ciProfileData* data = NULL;
 
     if (op->should_profile()) {
       ciMethod* method = op->profiled_method();
@@ -2005,7 +1925,8 @@
     case lir_cond_greater:      acond = Assembler::greater;      ncond = Assembler::lessEqual;    break;
     case lir_cond_belowEqual:   acond = Assembler::belowEqual;   ncond = Assembler::above;        break;
     case lir_cond_aboveEqual:   acond = Assembler::aboveEqual;   ncond = Assembler::below;        break;
-    default:                    ShouldNotReachHere();
+    default:                    acond = Assembler::equal;        ncond = Assembler::notEqual;
+                                ShouldNotReachHere();
   }
 
   if (opr1->is_cpu_register()) {
@@ -3181,27 +3102,23 @@
   assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point");
 
   int elem_size = type2aelembytes(basic_type);
-  int shift_amount;
   Address::ScaleFactor scale;
 
   switch (elem_size) {
     case 1 :
-      shift_amount = 0;
       scale = Address::times_1;
       break;
     case 2 :
-      shift_amount = 1;
       scale = Address::times_2;
       break;
     case 4 :
-      shift_amount = 2;
       scale = Address::times_4;
       break;
     case 8 :
-      shift_amount = 3;
       scale = Address::times_8;
       break;
     default:
+      scale = Address::no_scale;
       ShouldNotReachHere();
   }
 
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -195,7 +195,7 @@
 
 
 LIR_Opr LIRGenerator::load_immediate(int x, BasicType type) {
-  LIR_Opr r;
+  LIR_Opr r = NULL;
   if (type == T_LONG) {
     r = LIR_OprFact::longConst(x);
   } else if (type == T_INT) {
@@ -484,7 +484,7 @@
     __ cmp(lir_cond_equal, right.result(), LIR_OprFact::longConst(0));
     __ branch(lir_cond_equal, T_LONG, new DivByZeroStub(info));
 
-    address entry;
+    address entry = NULL;
     switch (x->op()) {
     case Bytecodes::_lrem:
       entry = CAST_FROM_FN_PTR(address, SharedRuntime::lrem);
@@ -1072,7 +1072,7 @@
 
 void LIRGenerator::do_Convert(Convert* x) {
   // flags that vary for the different operations and different SSE-settings
-  bool fixed_input, fixed_result, round_result, needs_stub;
+  bool fixed_input = false, fixed_result = false, round_result = false, needs_stub = false;
 
   switch (x->op()) {
     case Bytecodes::_i2l: // fall through
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -91,6 +91,8 @@
 
 define_pd_global(uintx, TypeProfileLevel, 111);
 
+define_pd_global(bool, CompactStrings, true);
+
 define_pd_global(bool, PreserveFramePointer, false);
 
 #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
--- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_32.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -48,7 +48,7 @@
 // between loads, which is much more efficient than lfence.
 
 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
-  const char *name;
+  const char *name = NULL;
   switch (type) {
     case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
     case T_BYTE:    name = "jni_fast_GetByteField";    break;
@@ -122,7 +122,7 @@
 
   slowcase_entry_pclist[count++] = __ pc();
   __ bind (slow);
-  address slow_case_addr;
+  address slow_case_addr = NULL;
   switch (type) {
     case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
     case T_BYTE:    slow_case_addr = jni_GetByteField_addr();    break;
@@ -256,7 +256,7 @@
 }
 
 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
-  const char *name;
+  const char *name = NULL;
   switch (type) {
     case T_FLOAT:  name = "jni_fast_GetFloatField";  break;
     case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
@@ -337,7 +337,7 @@
 
   slowcase_entry_pclist[count++] = __ pc();
   __ bind (slow);
-  address slow_case_addr;
+  address slow_case_addr = NULL;
   switch (type) {
     case T_FLOAT:  slow_case_addr = jni_GetFloatField_addr();  break;
     case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
--- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -51,7 +51,7 @@
 // since that may scratch r10!
 
 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
-  const char *name;
+  const char *name = NULL;
   switch (type) {
     case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
     case T_BYTE:    name = "jni_fast_GetByteField";    break;
@@ -111,7 +111,7 @@
 
   slowcase_entry_pclist[count++] = __ pc();
   __ bind (slow);
-  address slow_case_addr;
+  address slow_case_addr = NULL;
   switch (type) {
     case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
     case T_BYTE:    slow_case_addr = jni_GetByteField_addr();    break;
@@ -153,7 +153,7 @@
 }
 
 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
-  const char *name;
+  const char *name = NULL;
   switch (type) {
     case T_FLOAT:     name = "jni_fast_GetFloatField";     break;
     case T_DOUBLE:    name = "jni_fast_GetDoubleField";    break;
@@ -206,7 +206,7 @@
 
   slowcase_entry_pclist[count++] = __ pc();
   __ bind (slow);
-  address slow_case_addr;
+  address slow_case_addr = NULL;
   switch (type) {
     case T_FLOAT:     slow_case_addr = jni_GetFloatField_addr();  break;
     case T_DOUBLE:    slow_case_addr = jni_GetDoubleField_addr();
--- a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -85,6 +85,23 @@
   }
 }
 
+void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) {
+  address pc = _instructions->start() + pc_offset;
+  if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+#ifdef _LP64
+    address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
+    *((narrowKlass*) operand) = record_narrow_metadata_reference(constant);
+    TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+#else
+    fatal("compressed Klass* on 32bit");
+#endif
+  } else {
+    address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+    *((Metadata**) operand) = record_metadata_reference(constant);
+    TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+  }
+}
+
 void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
   address pc = _instructions->start() + pc_offset;
 
@@ -100,16 +117,6 @@
   TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset);
 }
 
-void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
-  if (cb->is_nmethod()) {
-    nmethod* nm = (nmethod*) cb;
-    nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
-  } else {
-    nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
-  }
-  _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
-}
-
 void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
   address pc = (address) inst;
   if (inst->is_call()) {
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -46,6 +46,9 @@
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 #include "crc32c.h"
+#ifdef COMPILER2
+#include "opto/intrinsicnode.hpp"
+#endif
 
 #ifdef PRODUCT
 #define BLOCK_COMMENT(str) /* nothing */
@@ -6299,25 +6302,34 @@
   }
 }
 
+#ifdef COMPILER2
+
 // IndexOf for constant substrings with size >= 8 chars
 // which don't need to be loaded through stack.
 void MacroAssembler::string_indexofC8(Register str1, Register str2,
                                       Register cnt1, Register cnt2,
                                       int int_cnt2,  Register result,
-                                      XMMRegister vec, Register tmp) {
+                                      XMMRegister vec, Register tmp,
+                                      int ae) {
   ShortBranchVerifier sbv(this);
   assert(UseSSE42Intrinsics, "SSE4.2 is required");
-
-  // This method uses pcmpestri instruction with bound registers
+  assert(ae != StrIntrinsicNode::LU, "Invalid encoding");
+
+  // This method uses the pcmpestri instruction with bound registers
   //   inputs:
   //     xmm - substring
   //     rax - substring length (elements count)
   //     mem - scanned string
   //     rdx - string length (elements count)
   //     0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
+  //     0xc - mode: 1100 (substring search) + 00 (unsigned bytes)
   //   outputs:
   //     rcx - matched index in string
   assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
+  int mode   = (ae == StrIntrinsicNode::LL) ? 0x0c : 0x0d; // bytes or shorts
+  int stride = (ae == StrIntrinsicNode::LL) ? 16 : 8; //UU, UL -> 8
+  Address::ScaleFactor scale1 = (ae == StrIntrinsicNode::LL) ? Address::times_1 : Address::times_2;
+  Address::ScaleFactor scale2 = (ae == StrIntrinsicNode::UL) ? Address::times_1 : scale1;
 
   Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR,
         RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR,
@@ -6326,20 +6338,28 @@
   // Note, inline_string_indexOf() generates checks:
   // if (substr.count > string.count) return -1;
   // if (substr.count == 0) return 0;
-  assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars");
+  assert(int_cnt2 >= stride, "this code is used only for cnt2 >= 8 chars");
 
   // Load substring.
-  movdqu(vec, Address(str2, 0));
+  if (ae == StrIntrinsicNode::UL) {
+    pmovzxbw(vec, Address(str2, 0));
+  } else {
+    movdqu(vec, Address(str2, 0));
+  }
   movl(cnt2, int_cnt2);
   movptr(result, str1); // string addr
 
-  if (int_cnt2 > 8) {
+  if (int_cnt2 > stride) {
     jmpb(SCAN_TO_SUBSTR);
 
     // Reload substr for rescan, this code
     // is executed only for large substrings (> 8 chars)
     bind(RELOAD_SUBSTR);
-    movdqu(vec, Address(str2, 0));
+    if (ae == StrIntrinsicNode::UL) {
+      pmovzxbw(vec, Address(str2, 0));
+    } else {
+      movdqu(vec, Address(str2, 0));
+    }
     negptr(cnt2); // Jumped here with negative cnt2, convert to positive
 
     bind(RELOAD_STR);
@@ -6358,15 +6378,15 @@
     cmpl(cnt1, cnt2);
     jccb(Assembler::negative, RET_NOT_FOUND);  // Left less then substring
 
-    addptr(result, 2);
+    addptr(result, (1<<scale1));
 
   } // (int_cnt2 > 8)
 
   // Scan string for start of substr in 16-byte vectors
   bind(SCAN_TO_SUBSTR);
-  pcmpestri(vec, Address(result, 0), 0x0d);
+  pcmpestri(vec, Address(result, 0), mode);
   jccb(Assembler::below, FOUND_CANDIDATE);   // CF == 1
-  subl(cnt1, 8);
+  subl(cnt1, stride);
   jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string
   cmpl(cnt1, cnt2);
   jccb(Assembler::negative, RET_NOT_FOUND);  // Left less then substring
@@ -6376,19 +6396,19 @@
   // Found a potential substr
   bind(FOUND_CANDIDATE);
   // Matched whole vector if first element matched (tmp(rcx) == 0).
-  if (int_cnt2 == 8) {
+  if (int_cnt2 == stride) {
     jccb(Assembler::overflow, RET_FOUND);    // OF == 1
   } else { // int_cnt2 > 8
     jccb(Assembler::overflow, FOUND_SUBSTR);
   }
   // After pcmpestri tmp(rcx) contains matched element index
   // Compute start addr of substr
-  lea(result, Address(result, tmp, Address::times_2));
+  lea(result, Address(result, tmp, scale1));
 
   // Make sure string is still long enough
   subl(cnt1, tmp);
   cmpl(cnt1, cnt2);
-  if (int_cnt2 == 8) {
+  if (int_cnt2 == stride) {
     jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR);
   } else { // int_cnt2 > 8
     jccb(Assembler::greaterEqual, MATCH_SUBSTR_HEAD);
@@ -6399,11 +6419,11 @@
   movl(result, -1);
   jmpb(EXIT);
 
-  if (int_cnt2 > 8) {
+  if (int_cnt2 > stride) {
     // This code is optimized for the case when whole substring
     // is matched if its head is matched.
     bind(MATCH_SUBSTR_HEAD);
-    pcmpestri(vec, Address(result, 0), 0x0d);
+    pcmpestri(vec, Address(result, 0), mode);
     // Reload only string if does not match
     jccb(Assembler::noOverflow, RELOAD_STR); // OF == 0
 
@@ -6412,31 +6432,41 @@
     bind(FOUND_SUBSTR);
     // First 8 chars are already matched.
     negptr(cnt2);
-    addptr(cnt2, 8);
+    addptr(cnt2, stride);
 
     bind(SCAN_SUBSTR);
-    subl(cnt1, 8);
-    cmpl(cnt2, -8); // Do not read beyond substring
+    subl(cnt1, stride);
+    cmpl(cnt2, -stride); // Do not read beyond substring
     jccb(Assembler::lessEqual, CONT_SCAN_SUBSTR);
     // Back-up strings to avoid reading beyond substring:
     // cnt1 = cnt1 - cnt2 + 8
     addl(cnt1, cnt2); // cnt2 is negative
-    addl(cnt1, 8);
-    movl(cnt2, 8); negptr(cnt2);
+    addl(cnt1, stride);
+    movl(cnt2, stride); negptr(cnt2);
     bind(CONT_SCAN_SUBSTR);
     if (int_cnt2 < (int)G) {
-      movdqu(vec, Address(str2, cnt2, Address::times_2, int_cnt2*2));
-      pcmpestri(vec, Address(result, cnt2, Address::times_2, int_cnt2*2), 0x0d);
+      int tail_off1 = int_cnt2<<scale1;
+      int tail_off2 = int_cnt2<<scale2;
+      if (ae == StrIntrinsicNode::UL) {
+        pmovzxbw(vec, Address(str2, cnt2, scale2, tail_off2));
+      } else {
+        movdqu(vec, Address(str2, cnt2, scale2, tail_off2));
+      }
+      pcmpestri(vec, Address(result, cnt2, scale1, tail_off1), mode);
     } else {
       // calculate index in register to avoid integer overflow (int_cnt2*2)
       movl(tmp, int_cnt2);
       addptr(tmp, cnt2);
-      movdqu(vec, Address(str2, tmp, Address::times_2, 0));
-      pcmpestri(vec, Address(result, tmp, Address::times_2, 0), 0x0d);
+      if (ae == StrIntrinsicNode::UL) {
+        pmovzxbw(vec, Address(str2, tmp, scale2, 0));
+      } else {
+        movdqu(vec, Address(str2, tmp, scale2, 0));
+      }
+      pcmpestri(vec, Address(result, tmp, scale1, 0), mode);
     }
     // Need to reload strings pointers if not matched whole vector
     jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0
-    addptr(cnt2, 8);
+    addptr(cnt2, stride);
     jcc(Assembler::negative, SCAN_SUBSTR);
     // Fall through if found full substring
 
@@ -6446,7 +6476,9 @@
   // Found result if we matched full small substring.
   // Compute substr offset
   subptr(result, str1);
-  shrl(result, 1); // index
+  if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) {
+    shrl(result, 1); // index
+  }
   bind(EXIT);
 
 } // string_indexofC8
@@ -6455,9 +6487,12 @@
 void MacroAssembler::string_indexof(Register str1, Register str2,
                                     Register cnt1, Register cnt2,
                                     int int_cnt2,  Register result,
-                                    XMMRegister vec, Register tmp) {
+                                    XMMRegister vec, Register tmp,
+                                    int ae) {
   ShortBranchVerifier sbv(this);
   assert(UseSSE42Intrinsics, "SSE4.2 is required");
+  assert(ae != StrIntrinsicNode::LU, "Invalid encoding");
+
   //
   // int_cnt2 is length of small (< 8 chars) constant substring
   // or (-1) for non constant substring in which case its length
@@ -6467,18 +6502,22 @@
   // if (substr.count > string.count) return -1;
   // if (substr.count == 0) return 0;
   //
-  assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0");
-
-  // This method uses pcmpestri instruction with bound registers
+  int stride = (ae == StrIntrinsicNode::LL) ? 16 : 8; //UU, UL -> 8
+  assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < stride), "should be != 0");
+  // This method uses the pcmpestri instruction with bound registers
   //   inputs:
   //     xmm - substring
   //     rax - substring length (elements count)
   //     mem - scanned string
   //     rdx - string length (elements count)
   //     0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
+  //     0xc - mode: 1100 (substring search) + 00 (unsigned bytes)
   //   outputs:
   //     rcx - matched index in string
   assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
+  int mode = (ae == StrIntrinsicNode::LL) ? 0x0c : 0x0d; // bytes or shorts
+  Address::ScaleFactor scale1 = (ae == StrIntrinsicNode::LL) ? Address::times_1 : Address::times_2;
+  Address::ScaleFactor scale2 = (ae == StrIntrinsicNode::UL) ? Address::times_1 : scale1;
 
   Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR,
         RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR,
@@ -6492,23 +6531,40 @@
     movptr(tmp, rsp); // save old SP
 
     if (int_cnt2 > 0) {     // small (< 8 chars) constant substring
-      if (int_cnt2 == 1) {  // One char
+      if (int_cnt2 == (1>>scale2)) { // One byte
+        assert((ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL), "Only possible for latin1 encoding");
+        load_unsigned_byte(result, Address(str2, 0));
+        movdl(vec, result); // move 32 bits
+      } else if (ae == StrIntrinsicNode::LL && int_cnt2 == 3) {  // Three bytes
+        // Not enough header space in 32-bit VM: 12+3 = 15.
+        movl(result, Address(str2, -1));
+        shrl(result, 8);
+        movdl(vec, result); // move 32 bits
+      } else if (ae != StrIntrinsicNode::UL && int_cnt2 == (2>>scale2)) {  // One char
         load_unsigned_short(result, Address(str2, 0));
         movdl(vec, result); // move 32 bits
-      } else if (int_cnt2 == 2) { // Two chars
+      } else if (ae != StrIntrinsicNode::UL && int_cnt2 == (4>>scale2)) { // Two chars
         movdl(vec, Address(str2, 0)); // move 32 bits
-      } else if (int_cnt2 == 4) { // Four chars
+      } else if (ae != StrIntrinsicNode::UL && int_cnt2 == (8>>scale2)) { // Four chars
         movq(vec, Address(str2, 0));  // move 64 bits
-      } else { // cnt2 = { 3, 5, 6, 7 }
+      } else { // cnt2 = { 3, 5, 6, 7 } || (ae == StrIntrinsicNode::UL && cnt2 ={2, ..., 7})
         // Array header size is 12 bytes in 32-bit VM
         // + 6 bytes for 3 chars == 18 bytes,
         // enough space to load vec and shift.
         assert(HeapWordSize*TypeArrayKlass::header_size() >= 12,"sanity");
-        movdqu(vec, Address(str2, (int_cnt2*2)-16));
-        psrldq(vec, 16-(int_cnt2*2));
+        if (ae == StrIntrinsicNode::UL) {
+          int tail_off = int_cnt2-8;
+          pmovzxbw(vec, Address(str2, tail_off));
+          psrldq(vec, -2*tail_off);
+        }
+        else {
+          int tail_off = int_cnt2*(1<<scale2);
+          movdqu(vec, Address(str2, tail_off-16));
+          psrldq(vec, 16-tail_off);
+        }
       }
     } else { // not constant substring
-      cmpl(cnt2, 8);
+      cmpl(cnt2, stride);
       jccb(Assembler::aboveEqual, BIG_STRINGS); // Both strings are big enough
 
       // We can read beyond string if srt+16 does not cross page boundary
@@ -6521,12 +6577,17 @@
 
       // Move small strings to stack to allow load 16 bytes into vec.
       subptr(rsp, 16);
-      int stk_offset = wordSize-2;
+      int stk_offset = wordSize-(1<<scale2);
       push(cnt2);
 
       bind(COPY_SUBSTR);
-      load_unsigned_short(result, Address(str2, cnt2, Address::times_2, -2));
-      movw(Address(rsp, cnt2, Address::times_2, stk_offset), result);
+      if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL) {
+        load_unsigned_byte(result, Address(str2, cnt2, scale2, -1));
+        movb(Address(rsp, cnt2, scale2, stk_offset), result);
+      } else if (ae == StrIntrinsicNode::UU) {
+        load_unsigned_short(result, Address(str2, cnt2, scale2, -2));
+        movw(Address(rsp, cnt2, scale2, stk_offset), result);
+      }
       decrement(cnt2);
       jccb(Assembler::notZero, COPY_SUBSTR);
 
@@ -6535,7 +6596,7 @@
     } // non constant
 
     bind(CHECK_STR);
-    cmpl(cnt1, 8);
+    cmpl(cnt1, stride);
     jccb(Assembler::aboveEqual, BIG_STRINGS);
 
     // Check cross page boundary.
@@ -6545,7 +6606,7 @@
     jccb(Assembler::belowEqual, BIG_STRINGS);
 
     subptr(rsp, 16);
-    int stk_offset = -2;
+    int stk_offset = -(1<<scale1);
     if (int_cnt2 < 0) { // not constant
       push(cnt2);
       stk_offset += wordSize;
@@ -6553,8 +6614,13 @@
     movl(cnt2, cnt1);
 
     bind(COPY_STR);
-    load_unsigned_short(result, Address(str1, cnt2, Address::times_2, -2));
-    movw(Address(rsp, cnt2, Address::times_2, stk_offset), result);
+    if (ae == StrIntrinsicNode::LL) {
+      load_unsigned_byte(result, Address(str1, cnt2, scale1, -1));
+      movb(Address(rsp, cnt2, scale1, stk_offset), result);
+    } else {
+      load_unsigned_short(result, Address(str1, cnt2, scale1, -2));
+      movw(Address(rsp, cnt2, scale1, stk_offset), result);
+    }
     decrement(cnt2);
     jccb(Assembler::notZero, COPY_STR);
 
@@ -6566,7 +6632,11 @@
     bind(BIG_STRINGS);
     // Load substring.
     if (int_cnt2 < 0) { // -1
-      movdqu(vec, Address(str2, 0));
+      if (ae == StrIntrinsicNode::UL) {
+        pmovzxbw(vec, Address(str2, 0));
+      } else {
+        movdqu(vec, Address(str2, 0));
+      }
       push(cnt2);       // substr count
       push(str2);       // substr addr
       push(str1);       // string addr
@@ -6597,37 +6667,43 @@
     bind(RELOAD_SUBSTR);
     movptr(str2, Address(rsp, 2*wordSize));
     movl(cnt2, Address(rsp, 3*wordSize));
-    movdqu(vec, Address(str2, 0));
+    if (ae == StrIntrinsicNode::UL) {
+      pmovzxbw(vec, Address(str2, 0));
+    } else {
+      movdqu(vec, Address(str2, 0));
+    }
     // We came here after the beginning of the substring was
     // matched but the rest of it was not so we need to search
     // again. Start from the next element after the previous match.
     subptr(str1, result); // Restore counter
-    shrl(str1, 1);
+    if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) {
+      shrl(str1, 1);
+    }
     addl(cnt1, str1);
     decrementl(cnt1);   // Shift to next element
     cmpl(cnt1, cnt2);
     jccb(Assembler::negative, RET_NOT_FOUND);  // Left less then substring
 
-    addptr(result, 2);
+    addptr(result, (1<<scale1));
   } // non constant
 
   // Scan string for start of substr in 16-byte vectors
   bind(SCAN_TO_SUBSTR);
   assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
-  pcmpestri(vec, Address(result, 0), 0x0d);
+  pcmpestri(vec, Address(result, 0), mode);
   jccb(Assembler::below, FOUND_CANDIDATE);   // CF == 1
-  subl(cnt1, 8);
+  subl(cnt1, stride);
   jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string
   cmpl(cnt1, cnt2);
   jccb(Assembler::negative, RET_NOT_FOUND);  // Left less then substring
   addptr(result, 16);
 
   bind(ADJUST_STR);
-  cmpl(cnt1, 8); // Do not read beyond string
+  cmpl(cnt1, stride); // Do not read beyond string
   jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR);
   // Back-up string to avoid reading beyond string.
-  lea(result, Address(result, cnt1, Address::times_2, -16));
-  movl(cnt1, 8);
+  lea(result, Address(result, cnt1, scale1, -16));
+  movl(cnt1, stride);
   jmpb(SCAN_TO_SUBSTR);
 
   // Found a potential substr
@@ -6646,13 +6722,12 @@
 
   bind(FOUND_SUBSTR);
   // Compute start addr of substr
-  lea(result, Address(result, tmp, Address::times_2));
-
+  lea(result, Address(result, tmp, scale1));
   if (int_cnt2 > 0) { // Constant substring
     // Repeat search for small substring (< 8 chars)
     // from new point without reloading substring.
     // Have to check that we don't read beyond string.
-    cmpl(tmp, 8-int_cnt2);
+    cmpl(tmp, stride-int_cnt2);
     jccb(Assembler::greater, ADJUST_STR);
     // Fall through if matched whole substring.
   } else { // non constant
@@ -6660,12 +6735,12 @@
 
     addl(tmp, cnt2);
     // Found result if we matched whole substring.
-    cmpl(tmp, 8);
+    cmpl(tmp, stride);
     jccb(Assembler::lessEqual, RET_FOUND);
 
     // Repeat search for small substring (<= 8 chars)
     // from new point 'str1' without reloading substring.
-    cmpl(cnt2, 8);
+    cmpl(cnt2, stride);
     // Have to check that we don't read beyond string.
     jccb(Assembler::lessEqual, ADJUST_STR);
 
@@ -6678,26 +6753,40 @@
     jccb(Assembler::equal, CHECK_NEXT);
 
     bind(SCAN_SUBSTR);
-    pcmpestri(vec, Address(str1, 0), 0x0d);
+    pcmpestri(vec, Address(str1, 0), mode);
     // Need to reload strings pointers if not matched whole vector
     jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0
 
     bind(CHECK_NEXT);
-    subl(cnt2, 8);
+    subl(cnt2, stride);
     jccb(Assembler::lessEqual, RET_FOUND_LONG); // Found full substring
     addptr(str1, 16);
-    addptr(str2, 16);
-    subl(cnt1, 8);
-    cmpl(cnt2, 8); // Do not read beyond substring
+    if (ae == StrIntrinsicNode::UL) {
+      addptr(str2, 8);
+    } else {
+      addptr(str2, 16);
+    }
+    subl(cnt1, stride);
+    cmpl(cnt2, stride); // Do not read beyond substring
     jccb(Assembler::greaterEqual, CONT_SCAN_SUBSTR);
     // Back-up strings to avoid reading beyond substring.
-    lea(str2, Address(str2, cnt2, Address::times_2, -16));
-    lea(str1, Address(str1, cnt2, Address::times_2, -16));
+
+    if (ae == StrIntrinsicNode::UL) {
+      lea(str2, Address(str2, cnt2, scale2, -8));
+      lea(str1, Address(str1, cnt2, scale1, -16));
+    } else {
+      lea(str2, Address(str2, cnt2, scale2, -16));
+      lea(str1, Address(str1, cnt2, scale1, -16));
+    }
     subl(cnt1, cnt2);
-    movl(cnt2, 8);
-    addl(cnt1, 8);
+    movl(cnt2, stride);
+    addl(cnt1, stride);
     bind(CONT_SCAN_SUBSTR);
-    movdqu(vec, Address(str2, 0));
+    if (ae == StrIntrinsicNode::UL) {
+      pmovzxbw(vec, Address(str2, 0));
+    } else {
+      movdqu(vec, Address(str2, 0));
+    }
     jmpb(SCAN_SUBSTR);
 
     bind(RET_FOUND_LONG);
@@ -6707,20 +6796,143 @@
   bind(RET_FOUND);
   // Compute substr offset
   subptr(result, str1);
-  shrl(result, 1); // index
-
+  if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) {
+    shrl(result, 1); // index
+  }
   bind(CLEANUP);
   pop(rsp); // restore SP
 
 } // string_indexof
 
-// Compare strings.
+void MacroAssembler::string_indexof_char(Register str1, Register cnt1, Register ch, Register result,
+                                         XMMRegister vec1, XMMRegister vec2, XMMRegister vec3, Register tmp) {
+  ShortBranchVerifier sbv(this);
+  assert(UseSSE42Intrinsics, "SSE4.2 is required");
+
+  int stride = 8;
+
+  Label FOUND_CHAR, SCAN_TO_CHAR, SCAN_TO_CHAR_LOOP,
+        SCAN_TO_8_CHAR, SCAN_TO_8_CHAR_LOOP, SCAN_TO_16_CHAR_LOOP,
+        RET_NOT_FOUND, SCAN_TO_8_CHAR_INIT,
+        FOUND_SEQ_CHAR, DONE_LABEL;
+
+  movptr(result, str1);
+  if (UseAVX >= 2) {
+    cmpl(cnt1, stride);
+    jccb(Assembler::less, SCAN_TO_CHAR_LOOP);
+    cmpl(cnt1, 2*stride);
+    jccb(Assembler::less, SCAN_TO_8_CHAR_INIT);
+    movdl(vec1, ch);
+    vpbroadcastw(vec1, vec1);
+    vpxor(vec2, vec2);
+    movl(tmp, cnt1);
+    andl(tmp, 0xFFFFFFF0);  //vector count (in chars)
+    andl(cnt1,0x0000000F);  //tail count (in chars)
+
+    bind(SCAN_TO_16_CHAR_LOOP);
+    vmovdqu(vec3, Address(result, 0));
+    vpcmpeqw(vec3, vec3, vec1, true);
+    vptest(vec2, vec3);
+    jcc(Assembler::carryClear, FOUND_CHAR);
+    addptr(result, 32);
+    subl(tmp, 2*stride);
+    jccb(Assembler::notZero, SCAN_TO_16_CHAR_LOOP);
+    jmp(SCAN_TO_8_CHAR);
+    bind(SCAN_TO_8_CHAR_INIT);
+    movdl(vec1, ch);
+    pshuflw(vec1, vec1, 0x00);
+    pshufd(vec1, vec1, 0);
+    pxor(vec2, vec2);
+  }
+  if (UseAVX >= 2 || UseSSE42Intrinsics) {
+    bind(SCAN_TO_8_CHAR);
+    cmpl(cnt1, stride);
+    if (UseAVX >= 2) {
+      jccb(Assembler::less, SCAN_TO_CHAR);
+    }
+    if (!(UseAVX >= 2)) {
+      jccb(Assembler::less, SCAN_TO_CHAR_LOOP);
+      movdl(vec1, ch);
+      pshuflw(vec1, vec1, 0x00);
+      pshufd(vec1, vec1, 0);
+      pxor(vec2, vec2);
+    }
+    movl(tmp, cnt1);
+    andl(tmp, 0xFFFFFFF8);  //vector count (in chars)
+    andl(cnt1,0x00000007);  //tail count (in chars)
+
+    bind(SCAN_TO_8_CHAR_LOOP);
+    movdqu(vec3, Address(result, 0));
+    pcmpeqw(vec3, vec1);
+    ptest(vec2, vec3);
+    jcc(Assembler::carryClear, FOUND_CHAR);
+    addptr(result, 16);
+    subl(tmp, stride);
+    jccb(Assembler::notZero, SCAN_TO_8_CHAR_LOOP);
+  }
+  bind(SCAN_TO_CHAR);
+  testl(cnt1, cnt1);
+  jcc(Assembler::zero, RET_NOT_FOUND);
+
+  bind(SCAN_TO_CHAR_LOOP);
+  load_unsigned_short(tmp, Address(result, 0));
+  cmpl(ch, tmp);
+  jccb(Assembler::equal, FOUND_SEQ_CHAR);
+  addptr(result, 2);
+  subl(cnt1, 1);
+  jccb(Assembler::zero, RET_NOT_FOUND);
+  jmp(SCAN_TO_CHAR_LOOP);
+
+  bind(RET_NOT_FOUND);
+  movl(result, -1);
+  jmpb(DONE_LABEL);
+
+  if (UseAVX >= 2 || UseSSE42Intrinsics) {
+    bind(FOUND_CHAR);
+    if (UseAVX >= 2) {
+      vpmovmskb(tmp, vec3);
+    } else {
+      pmovmskb(tmp, vec3);
+    }
+    bsfl(ch, tmp);
+    addl(result, ch);
+  }
+
+  bind(FOUND_SEQ_CHAR);
+  subptr(result, str1);
+  shrl(result, 1);
+
+  bind(DONE_LABEL);
+} // string_indexof_char
+
+// helper function for string_compare
+void MacroAssembler::load_next_elements(Register elem1, Register elem2, Register str1, Register str2,
+                                        Address::ScaleFactor scale, Address::ScaleFactor scale1,
+                                        Address::ScaleFactor scale2, Register index, int ae) {
+  if (ae == StrIntrinsicNode::LL) {
+    load_unsigned_byte(elem1, Address(str1, index, scale, 0));
+    load_unsigned_byte(elem2, Address(str2, index, scale, 0));
+  } else if (ae == StrIntrinsicNode::UU) {
+    load_unsigned_short(elem1, Address(str1, index, scale, 0));
+    load_unsigned_short(elem2, Address(str2, index, scale, 0));
+  } else {
+    load_unsigned_byte(elem1, Address(str1, index, scale1, 0));
+    load_unsigned_short(elem2, Address(str2, index, scale2, 0));
+  }
+}
+
+// Compare strings, used for char[] and byte[].
 void MacroAssembler::string_compare(Register str1, Register str2,
                                     Register cnt1, Register cnt2, Register result,
-                                    XMMRegister vec1) {
+                                    XMMRegister vec1, int ae) {
   ShortBranchVerifier sbv(this);
   Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL;
-
+  int stride, stride2, adr_stride, adr_stride1, adr_stride2;
+  Address::ScaleFactor scale, scale1, scale2;
+
+  if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
+    shrl(cnt2, 1);
+  }
   // Compute the minimum of the string lengths and the
   // difference of the string lengths (stack).
   // Do the conditional move stuff
@@ -6732,32 +6944,68 @@
   // Is the minimum length zero?
   testl(cnt2, cnt2);
   jcc(Assembler::zero, LENGTH_DIFF_LABEL);
-
-  // Compare first characters
-  load_unsigned_short(result, Address(str1, 0));
-  load_unsigned_short(cnt1, Address(str2, 0));
+  if (ae == StrIntrinsicNode::LL) {
+    // Load first bytes
+    load_unsigned_byte(result, Address(str1, 0));
+    load_unsigned_byte(cnt1, Address(str2, 0));
+  } else if (ae == StrIntrinsicNode::UU) {
+    // Load first characters
+    load_unsigned_short(result, Address(str1, 0));
+    load_unsigned_short(cnt1, Address(str2, 0));
+  } else {
+    load_unsigned_byte(result, Address(str1, 0));
+    load_unsigned_short(cnt1, Address(str2, 0));
+  }
   subl(result, cnt1);
   jcc(Assembler::notZero,  POP_LABEL);
+
+  if (ae == StrIntrinsicNode::UU) {
+    // Divide length by 2 to get number of chars
+    shrl(cnt2, 1);
+  }
   cmpl(cnt2, 1);
   jcc(Assembler::equal, LENGTH_DIFF_LABEL);
 
-  // Check if the strings start at the same location.
-  cmpptr(str1, str2);
-  jcc(Assembler::equal, LENGTH_DIFF_LABEL);
-
-  Address::ScaleFactor scale = Address::times_2;
-  int stride = 8;
+  // Check if the strings start at the same location and setup scale and stride
+  if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+    cmpptr(str1, str2);
+    jcc(Assembler::equal, LENGTH_DIFF_LABEL);
+    if (ae == StrIntrinsicNode::LL) {
+      scale = Address::times_1;
+      stride = 16;
+    } else {
+      scale = Address::times_2;
+      stride = 8;
+    }
+  } else {
+    scale = Address::no_scale;  // not used
+    scale1 = Address::times_1;
+    scale2 = Address::times_2;
+    stride = 8;
+  }
 
   if (UseAVX >= 2 && UseSSE42Intrinsics) {
     Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
     Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
     Label COMPARE_TAIL_LONG;
     int pcmpmask = 0x19;
+    if (ae == StrIntrinsicNode::LL) {
+      pcmpmask &= ~0x01;
+    }
 
     // Setup to compare 16-chars (32-bytes) vectors,
     // start from first character again because it has aligned address.
-    int stride2 = 16;
-    int adr_stride  = stride  << scale;
+    if (ae == StrIntrinsicNode::LL) {
+      stride2 = 32;
+    } else {
+      stride2 = 16;
+    }
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      adr_stride = stride << scale;
+    } else {
+      adr_stride1 = 8;  //stride << scale1;
+      adr_stride2 = 16; //stride << scale2;
+    }
 
     assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
     // rax and rdx are used by pcmpestri as elements counters
@@ -6767,26 +7015,39 @@
 
     // fast path : compare first 2 8-char vectors.
     bind(COMPARE_16_CHARS);
-    movdqu(vec1, Address(str1, 0));
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      movdqu(vec1, Address(str1, 0));
+    } else {
+      pmovzxbw(vec1, Address(str1, 0));
+    }
     pcmpestri(vec1, Address(str2, 0), pcmpmask);
     jccb(Assembler::below, COMPARE_INDEX_CHAR);
 
-    movdqu(vec1, Address(str1, adr_stride));
-    pcmpestri(vec1, Address(str2, adr_stride), pcmpmask);
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      movdqu(vec1, Address(str1, adr_stride));
+      pcmpestri(vec1, Address(str2, adr_stride), pcmpmask);
+    } else {
+      pmovzxbw(vec1, Address(str1, adr_stride1));
+      pcmpestri(vec1, Address(str2, adr_stride2), pcmpmask);
+    }
     jccb(Assembler::aboveEqual, COMPARE_WIDE_VECTORS);
     addl(cnt1, stride);
 
     // Compare the characters at index in cnt1
-    bind(COMPARE_INDEX_CHAR); //cnt1 has the offset of the mismatching character
-    load_unsigned_short(result, Address(str1, cnt1, scale));
-    load_unsigned_short(cnt2, Address(str2, cnt1, scale));
+    bind(COMPARE_INDEX_CHAR); // cnt1 has the offset of the mismatching character
+    load_next_elements(result, cnt2, str1, str2, scale, scale1, scale2, cnt1, ae);
     subl(result, cnt2);
     jmp(POP_LABEL);
 
     // Setup the registers to start vector comparison loop
     bind(COMPARE_WIDE_VECTORS);
-    lea(str1, Address(str1, result, scale));
-    lea(str2, Address(str2, result, scale));
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      lea(str1, Address(str1, result, scale));
+      lea(str2, Address(str2, result, scale));
+    } else {
+      lea(str1, Address(str1, result, scale1));
+      lea(str2, Address(str2, result, scale2));
+    }
     subl(result, stride2);
     subl(cnt2, stride2);
     jccb(Assembler::zero, COMPARE_WIDE_TAIL);
@@ -6794,8 +7055,13 @@
 
     //  In a loop, compare 16-chars (32-bytes) at once using (vpxor+vptest)
     bind(COMPARE_WIDE_VECTORS_LOOP);
-    vmovdqu(vec1, Address(str1, result, scale));
-    vpxor(vec1, Address(str2, result, scale));
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      vmovdqu(vec1, Address(str1, result, scale));
+      vpxor(vec1, Address(str2, result, scale));
+    } else {
+      vpmovzxbw(vec1, Address(str1, result, scale1));
+      vpxor(vec1, Address(str2, result, scale2));
+    }
     vptest(vec1, vec1);
     jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
     addptr(result, stride2);
@@ -6818,8 +7084,13 @@
     bind(VECTOR_NOT_EQUAL);
     // clean upper bits of YMM registers
     vpxor(vec1, vec1);
-    lea(str1, Address(str1, result, scale));
-    lea(str2, Address(str2, result, scale));
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      lea(str1, Address(str1, result, scale));
+      lea(str2, Address(str2, result, scale));
+    } else {
+      lea(str1, Address(str1, result, scale1));
+      lea(str2, Address(str2, result, scale2));
+    }
     jmp(COMPARE_16_CHARS);
 
     // Compare tail chars, length between 1 to 15 chars
@@ -6828,13 +7099,22 @@
     cmpl(cnt2, stride);
     jccb(Assembler::less, COMPARE_SMALL_STR);
 
-    movdqu(vec1, Address(str1, 0));
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      movdqu(vec1, Address(str1, 0));
+    } else {
+      pmovzxbw(vec1, Address(str1, 0));
+    }
     pcmpestri(vec1, Address(str2, 0), pcmpmask);
     jcc(Assembler::below, COMPARE_INDEX_CHAR);
     subptr(cnt2, stride);
     jccb(Assembler::zero, LENGTH_DIFF_LABEL);
-    lea(str1, Address(str1, result, scale));
-    lea(str2, Address(str2, result, scale));
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      lea(str1, Address(str1, result, scale));
+      lea(str2, Address(str2, result, scale));
+    } else {
+      lea(str1, Address(str1, result, scale1));
+      lea(str2, Address(str2, result, scale2));
+    }
     negptr(cnt2);
     jmpb(WHILE_HEAD_LABEL);
 
@@ -6846,10 +7126,17 @@
     // start from first character again because it has aligned address.
     movl(result, cnt2);
     andl(cnt2, ~(stride - 1));   // cnt2 holds the vector count
+    if (ae == StrIntrinsicNode::LL) {
+      pcmpmask &= ~0x01;
+    }
     jccb(Assembler::zero, COMPARE_TAIL);
-
-    lea(str1, Address(str1, result, scale));
-    lea(str2, Address(str2, result, scale));
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      lea(str1, Address(str1, result, scale));
+      lea(str2, Address(str2, result, scale));
+    } else {
+      lea(str1, Address(str1, result, scale1));
+      lea(str2, Address(str2, result, scale2));
+    }
     negptr(result);
 
     // pcmpestri
@@ -6865,8 +7152,13 @@
     assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
 
     bind(COMPARE_WIDE_VECTORS);
-    movdqu(vec1, Address(str1, result, scale));
-    pcmpestri(vec1, Address(str2, result, scale), pcmpmask);
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      movdqu(vec1, Address(str1, result, scale));
+      pcmpestri(vec1, Address(str2, result, scale), pcmpmask);
+    } else {
+      pmovzxbw(vec1, Address(str1, result, scale1));
+      pcmpestri(vec1, Address(str2, result, scale2), pcmpmask);
+    }
     // After pcmpestri cnt1(rcx) contains mismatched element index
 
     jccb(Assembler::below, VECTOR_NOT_EQUAL);  // CF==1
@@ -6881,15 +7173,19 @@
     movl(cnt2, stride);
     movl(result, stride);
     negptr(result);
-    movdqu(vec1, Address(str1, result, scale));
-    pcmpestri(vec1, Address(str2, result, scale), pcmpmask);
+    if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+      movdqu(vec1, Address(str1, result, scale));
+      pcmpestri(vec1, Address(str2, result, scale), pcmpmask);
+    } else {
+      pmovzxbw(vec1, Address(str1, result, scale1));
+      pcmpestri(vec1, Address(str2, result, scale2), pcmpmask);
+    }
     jccb(Assembler::aboveEqual, LENGTH_DIFF_LABEL);
 
     // Mismatched characters in the vectors
     bind(VECTOR_NOT_EQUAL);
     addptr(cnt1, result);
-    load_unsigned_short(result, Address(str1, cnt1, scale));
-    load_unsigned_short(cnt2, Address(str2, cnt1, scale));
+    load_next_elements(result, cnt2, str1, str2, scale, scale1, scale2, cnt1, ae);
     subl(result, cnt2);
     jmpb(POP_LABEL);
 
@@ -6898,15 +7194,19 @@
     // Fallthru to tail compare
   }
   // Shift str2 and str1 to the end of the arrays, negate min
-  lea(str1, Address(str1, cnt2, scale));
-  lea(str2, Address(str2, cnt2, scale));
+  if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+    lea(str1, Address(str1, cnt2, scale));
+    lea(str2, Address(str2, cnt2, scale));
+  } else {
+    lea(str1, Address(str1, cnt2, scale1));
+    lea(str2, Address(str2, cnt2, scale2));
+  }
   decrementl(cnt2);  // first character was compared already
   negptr(cnt2);
 
   // Compare the rest of the elements
   bind(WHILE_HEAD_LABEL);
-  load_unsigned_short(result, Address(str1, cnt2, scale, 0));
-  load_unsigned_short(cnt1, Address(str2, cnt2, scale, 0));
+  load_next_elements(result, cnt1, str1, str2, scale, scale1, scale2, cnt2, ae);
   subl(result, cnt1);
   jccb(Assembler::notZero, POP_LABEL);
   increment(cnt2);
@@ -6915,6 +7215,10 @@
   // Strings are equal up to min length.  Return the length difference.
   bind(LENGTH_DIFF_LABEL);
   pop(result);
+  if (ae == StrIntrinsicNode::UU) {
+    // Divide diff by 2 to get number of chars
+    sarl(result, 1);
+  }
   jmpb(DONE_LABEL);
 
   // Discard the stored length difference
@@ -6923,23 +7227,164 @@
 
   // That's it
   bind(DONE_LABEL);
-}
-
-// Compare char[] arrays aligned to 4 bytes or substrings.
-void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2,
-                                        Register limit, Register result, Register chr,
-                                        XMMRegister vec1, XMMRegister vec2) {
+  if(ae == StrIntrinsicNode::UL) {
+    negl(result);
+  }
+}
+
+// Search for Non-ASCII character (Negative byte value) in a byte array,
+// return true if it has any and false otherwise.
+void MacroAssembler::has_negatives(Register ary1, Register len,
+                                   Register result, Register tmp1,
+                                   XMMRegister vec1, XMMRegister vec2) {
+
+  // rsi: byte array
+  // rcx: len
+  // rax: result
   ShortBranchVerifier sbv(this);
-  Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR;
+  assert_different_registers(ary1, len, result, tmp1);
+  assert_different_registers(vec1, vec2);
+  Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_CHAR, COMPARE_VECTORS, COMPARE_BYTE;
+
+  // len == 0
+  testl(len, len);
+  jcc(Assembler::zero, FALSE_LABEL);
+
+  movl(result, len); // copy
+
+  if (UseAVX >= 2) {
+    // With AVX2, use 32-byte vector compare
+    Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
+
+    // Compare 32-byte vectors
+    andl(result, 0x0000001f);  //   tail count (in bytes)
+    andl(len, 0xffffffe0);   // vector count (in bytes)
+    jccb(Assembler::zero, COMPARE_TAIL);
+
+    lea(ary1, Address(ary1, len, Address::times_1));
+    negptr(len);
+
+    movl(tmp1, 0x80808080);   // create mask to test for Unicode chars in vector
+    movdl(vec2, tmp1);
+    vpbroadcastd(vec2, vec2);
+
+    bind(COMPARE_WIDE_VECTORS);
+    vmovdqu(vec1, Address(ary1, len, Address::times_1));
+    vptest(vec1, vec2);
+    jccb(Assembler::notZero, TRUE_LABEL);
+    addptr(len, 32);
+    jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
+
+    testl(result, result);
+    jccb(Assembler::zero, FALSE_LABEL);
+
+    vmovdqu(vec1, Address(ary1, result, Address::times_1, -32));
+    vptest(vec1, vec2);
+    jccb(Assembler::notZero, TRUE_LABEL);
+    jmpb(FALSE_LABEL);
+
+    bind(COMPARE_TAIL); // len is zero
+    movl(len, result);
+    // Fallthru to tail compare
+  } else if (UseSSE42Intrinsics) {
+    // With SSE4.2, use double quad vector compare
+    Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
+
+    // Compare 16-byte vectors
+    andl(result, 0x0000000f);  //   tail count (in bytes)
+    andl(len, 0xfffffff0);   // vector count (in bytes)
+    jccb(Assembler::zero, COMPARE_TAIL);
+
+    lea(ary1, Address(ary1, len, Address::times_1));
+    negptr(len);
+
+    movl(tmp1, 0x80808080);
+    movdl(vec2, tmp1);
+    pshufd(vec2, vec2, 0);
+
+    bind(COMPARE_WIDE_VECTORS);
+    movdqu(vec1, Address(ary1, len, Address::times_1));
+    ptest(vec1, vec2);
+    jccb(Assembler::notZero, TRUE_LABEL);
+    addptr(len, 16);
+    jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
+
+    testl(result, result);
+    jccb(Assembler::zero, FALSE_LABEL);
+
+    movdqu(vec1, Address(ary1, result, Address::times_1, -16));
+    ptest(vec1, vec2);
+    jccb(Assembler::notZero, TRUE_LABEL);
+    jmpb(FALSE_LABEL);
+
+    bind(COMPARE_TAIL); // len is zero
+    movl(len, result);
+    // Fallthru to tail compare
+  }
+
+  // Compare 4-byte vectors
+  andl(len, 0xfffffffc); // vector count (in bytes)
+  jccb(Assembler::zero, COMPARE_CHAR);
+
+  lea(ary1, Address(ary1, len, Address::times_1));
+  negptr(len);
+
+  bind(COMPARE_VECTORS);
+  movl(tmp1, Address(ary1, len, Address::times_1));
+  andl(tmp1, 0x80808080);
+  jccb(Assembler::notZero, TRUE_LABEL);
+  addptr(len, 4);
+  jcc(Assembler::notZero, COMPARE_VECTORS);
+
+  // Compare trailing char (final 2 bytes), if any
+  bind(COMPARE_CHAR);
+  testl(result, 0x2);   // tail  char
+  jccb(Assembler::zero, COMPARE_BYTE);
+  load_unsigned_short(tmp1, Address(ary1, 0));
+  andl(tmp1, 0x00008080);
+  jccb(Assembler::notZero, TRUE_LABEL);
+  subptr(result, 2);
+  lea(ary1, Address(ary1, 2));
+
+  bind(COMPARE_BYTE);
+  testl(result, 0x1);   // tail  byte
+  jccb(Assembler::zero, FALSE_LABEL);
+  load_unsigned_byte(tmp1, Address(ary1, 0));
+  andl(tmp1, 0x00000080);
+  jccb(Assembler::notEqual, TRUE_LABEL);
+  jmpb(FALSE_LABEL);
+
+  bind(TRUE_LABEL);
+  movl(result, 1);   // return true
+  jmpb(DONE);
+
+  bind(FALSE_LABEL);
+  xorl(result, result); // return false
+
+  // That's it
+  bind(DONE);
+  if (UseAVX >= 2) {
+    // clean upper bits of YMM registers
+    vpxor(vec1, vec1);
+    vpxor(vec2, vec2);
+  }
+}
+
+// Compare char[] or byte[] arrays aligned to 4 bytes or substrings.
+void MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register ary2,
+                                   Register limit, Register result, Register chr,
+                                   XMMRegister vec1, XMMRegister vec2, bool is_char) {
+  ShortBranchVerifier sbv(this);
+  Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR, COMPARE_BYTE;
 
   int length_offset  = arrayOopDesc::length_offset_in_bytes();
-  int base_offset    = arrayOopDesc::base_offset_in_bytes(T_CHAR);
-
-  // Check the input args
-  cmpptr(ary1, ary2);
-  jcc(Assembler::equal, TRUE_LABEL);
+  int base_offset    = arrayOopDesc::base_offset_in_bytes(is_char ? T_CHAR : T_BYTE);
 
   if (is_array_equ) {
+    // Check the input args
+    cmpptr(ary1, ary2);
+    jcc(Assembler::equal, TRUE_LABEL);
+
     // Need additional checks for arrays_equals.
     testptr(ary1, ary1);
     jcc(Assembler::zero, FALSE_LABEL);
@@ -6962,7 +7407,10 @@
     lea(ary2, Address(ary2, base_offset));
   }
 
-  shll(limit, 1);      // byte count != 0
+  if (is_array_equ && is_char) {
+    // arrays_equals when used for char[].
+    shll(limit, 1);      // byte count != 0
+  }
   movl(result, limit); // copy
 
   if (UseAVX >= 2) {
@@ -6970,7 +7418,7 @@
     Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
 
     // Compare 32-byte vectors
-    andl(result, 0x0000001e);  //   tail count (in bytes)
+    andl(result, 0x0000001f);  //   tail count (in bytes)
     andl(limit, 0xffffffe0);   // vector count (in bytes)
     jccb(Assembler::zero, COMPARE_TAIL);
 
@@ -7007,7 +7455,7 @@
     Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
 
     // Compare 16-byte vectors
-    andl(result, 0x0000000e);  //   tail count (in bytes)
+    andl(result, 0x0000000f);  //   tail count (in bytes)
     andl(limit, 0xfffffff0);   // vector count (in bytes)
     jccb(Assembler::zero, COMPARE_TAIL);
 
@@ -7059,12 +7507,26 @@
   // Compare trailing char (final 2 bytes), if any
   bind(COMPARE_CHAR);
   testl(result, 0x2);   // tail  char
-  jccb(Assembler::zero, TRUE_LABEL);
+  jccb(Assembler::zero, COMPARE_BYTE);
   load_unsigned_short(chr, Address(ary1, 0));
   load_unsigned_short(limit, Address(ary2, 0));
   cmpl(chr, limit);
   jccb(Assembler::notEqual, FALSE_LABEL);
 
+  if (is_array_equ && is_char) {
+    bind(COMPARE_BYTE);
+  } else {
+    lea(ary1, Address(ary1, 2));
+    lea(ary2, Address(ary2, 2));
+
+    bind(COMPARE_BYTE);
+    testl(result, 0x1);   // tail  byte
+    jccb(Assembler::zero, TRUE_LABEL);
+    load_unsigned_byte(chr, Address(ary1, 0));
+    load_unsigned_byte(limit, Address(ary2, 0));
+    cmpl(chr, limit);
+    jccb(Assembler::notEqual, FALSE_LABEL);
+  }
   bind(TRUE_LABEL);
   movl(result, 1);   // return true
   jmpb(DONE);
@@ -7081,6 +7543,8 @@
   }
 }
 
+#endif
+
 void MacroAssembler::generate_fill(BasicType t, bool aligned,
                                    Register to, Register value, Register count,
                                    Register rtmp, XMMRegister xtmp) {
@@ -9085,6 +9549,179 @@
 #undef BLOCK_COMMENT
 
 
+// Compress char[] array to byte[].
+void MacroAssembler::char_array_compress(Register src, Register dst, Register len,
+                                         XMMRegister tmp1Reg, XMMRegister tmp2Reg,
+                                         XMMRegister tmp3Reg, XMMRegister tmp4Reg,
+                                         Register tmp5, Register result) {
+  Label copy_chars_loop, return_length, return_zero, done;
+
+  // rsi: src
+  // rdi: dst
+  // rdx: len
+  // rcx: tmp5
+  // rax: result
+
+  // rsi holds start addr of source char[] to be compressed
+  // rdi holds start addr of destination byte[]
+  // rdx holds length
+
+  assert(len != result, "");
+
+  // save length for return
+  push(len);
+
+  if (UseSSE42Intrinsics) {
+    Label copy_32_loop, copy_16, copy_tail;
+
+    movl(result, len);
+    movl(tmp5, 0xff00ff00);   // create mask to test for Unicode chars in vectors
+
+    // vectored compression
+    andl(len, 0xfffffff0);    // vector count (in chars)
+    andl(result, 0x0000000f);    // tail count (in chars)
+    testl(len, len);
+    jccb(Assembler::zero, copy_16);
+
+    // compress 16 chars per iter
+    movdl(tmp1Reg, tmp5);
+    pshufd(tmp1Reg, tmp1Reg, 0);   // store Unicode mask in tmp1Reg
+    pxor(tmp4Reg, tmp4Reg);
+
+    lea(src, Address(src, len, Address::times_2));
+    lea(dst, Address(dst, len, Address::times_1));
+    negptr(len);
+
+    bind(copy_32_loop);
+    movdqu(tmp2Reg, Address(src, len, Address::times_2));     // load 1st 8 characters
+    por(tmp4Reg, tmp2Reg);
+    movdqu(tmp3Reg, Address(src, len, Address::times_2, 16)); // load next 8 characters
+    por(tmp4Reg, tmp3Reg);
+    ptest(tmp4Reg, tmp1Reg);       // check for Unicode chars in next vector
+    jcc(Assembler::notZero, return_zero);
+    packuswb(tmp2Reg, tmp3Reg);    // only ASCII chars; compress each to 1 byte
+    movdqu(Address(dst, len, Address::times_1), tmp2Reg);
+    addptr(len, 16);
+    jcc(Assembler::notZero, copy_32_loop);
+
+    // compress next vector of 8 chars (if any)
+    bind(copy_16);
+    movl(len, result);
+    andl(len, 0xfffffff8);    // vector count (in chars)
+    andl(result, 0x00000007);    // tail count (in chars)
+    testl(len, len);
+    jccb(Assembler::zero, copy_tail);
+
+    movdl(tmp1Reg, tmp5);
+    pshufd(tmp1Reg, tmp1Reg, 0);   // store Unicode mask in tmp1Reg
+    pxor(tmp3Reg, tmp3Reg);
+
+    movdqu(tmp2Reg, Address(src, 0));
+    ptest(tmp2Reg, tmp1Reg);       // check for Unicode chars in vector
+    jccb(Assembler::notZero, return_zero);
+    packuswb(tmp2Reg, tmp3Reg);    // only LATIN1 chars; compress each to 1 byte
+    movq(Address(dst, 0), tmp2Reg);
+    addptr(src, 16);
+    addptr(dst, 8);
+
+    bind(copy_tail);
+    movl(len, result);
+  }
+  // compress 1 char per iter
+  testl(len, len);
+  jccb(Assembler::zero, return_length);
+  lea(src, Address(src, len, Address::times_2));
+  lea(dst, Address(dst, len, Address::times_1));
+  negptr(len);
+
+  bind(copy_chars_loop);
+  load_unsigned_short(result, Address(src, len, Address::times_2));
+  testl(result, 0xff00);      // check if Unicode char
+  jccb(Assembler::notZero, return_zero);
+  movb(Address(dst, len, Address::times_1), result);  // ASCII char; compress to 1 byte
+  increment(len);
+  jcc(Assembler::notZero, copy_chars_loop);
+
+  // if compression succeeded, return length
+  bind(return_length);
+  pop(result);
+  jmpb(done);
+
+  // if compression failed, return 0
+  bind(return_zero);
+  xorl(result, result);
+  addptr(rsp, wordSize);
+
+  bind(done);
+}
+
+// Inflate byte[] array to char[].
+void MacroAssembler::byte_array_inflate(Register src, Register dst, Register len,
+                                        XMMRegister tmp1, Register tmp2) {
+  Label copy_chars_loop, done;
+
+  // rsi: src
+  // rdi: dst
+  // rdx: len
+  // rcx: tmp2
+
+  // rsi holds start addr of source byte[] to be inflated
+  // rdi holds start addr of destination char[]
+  // rdx holds length
+  assert_different_registers(src, dst, len, tmp2);
+
+  if (UseSSE42Intrinsics) {
+    Label copy_8_loop, copy_bytes, copy_tail;
+
+    movl(tmp2, len);
+    andl(tmp2, 0x00000007);   // tail count (in chars)
+    andl(len, 0xfffffff8);    // vector count (in chars)
+    jccb(Assembler::zero, copy_tail);
+
+    // vectored inflation
+    lea(src, Address(src, len, Address::times_1));
+    lea(dst, Address(dst, len, Address::times_2));
+    negptr(len);
+
+    // inflate 8 chars per iter
+    bind(copy_8_loop);
+    pmovzxbw(tmp1, Address(src, len, Address::times_1));  // unpack to 8 words
+    movdqu(Address(dst, len, Address::times_2), tmp1);
+    addptr(len, 8);
+    jcc(Assembler::notZero, copy_8_loop);
+
+    bind(copy_tail);
+    movl(len, tmp2);
+
+    cmpl(len, 4);
+    jccb(Assembler::less, copy_bytes);
+
+    movdl(tmp1, Address(src, 0));  // load 4 byte chars
+    pmovzxbw(tmp1, tmp1);
+    movq(Address(dst, 0), tmp1);
+    subptr(len, 4);
+    addptr(src, 4);
+    addptr(dst, 8);
+
+    bind(copy_bytes);
+  }
+  testl(len, len);
+  jccb(Assembler::zero, done);
+  lea(src, Address(src, len, Address::times_1));
+  lea(dst, Address(dst, len, Address::times_2));
+  negptr(len);
+
+  // inflate 1 char per iter
+  bind(copy_chars_loop);
+  load_unsigned_byte(tmp2, Address(src, len, Address::times_1));  // load byte char
+  movw(Address(dst, len, Address::times_2), tmp2);  // inflate byte char to word
+  increment(len);
+  jcc(Assembler::notZero, copy_chars_loop);
+
+  bind(done);
+}
+
+
 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) {
   switch (cond) {
     // Note some conditions are synonyms for others
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,6 @@
 #include "utilities/macros.hpp"
 #include "runtime/rtmLocking.hpp"
 
-
 // MacroAssembler extends Assembler by frequently used macros.
 //
 // Instructions for which a 'better' code sequence exists depending
@@ -1212,32 +1211,50 @@
   // clear memory of size 'cnt' qwords, starting at 'base'.
   void clear_mem(Register base, Register cnt, Register rtmp);
 
+#ifdef COMPILER2
+  void string_indexof_char(Register str1, Register cnt1, Register ch, Register result,
+                           XMMRegister vec1, XMMRegister vec2, XMMRegister vec3, Register tmp);
+
   // IndexOf strings.
   // Small strings are loaded through stack if they cross page boundary.
   void string_indexof(Register str1, Register str2,
                       Register cnt1, Register cnt2,
                       int int_cnt2,  Register result,
-                      XMMRegister vec, Register tmp);
+                      XMMRegister vec, Register tmp,
+                      int ae);
 
   // IndexOf for constant substrings with size >= 8 elements
   // which don't need to be loaded through stack.
   void string_indexofC8(Register str1, Register str2,
                       Register cnt1, Register cnt2,
                       int int_cnt2,  Register result,
-                      XMMRegister vec, Register tmp);
+                      XMMRegister vec, Register tmp,
+                      int ae);
 
     // Smallest code: we don't need to load through stack,
     // check string tail.
 
+  // helper function for string_compare
+  void load_next_elements(Register elem1, Register elem2, Register str1, Register str2,
+                          Address::ScaleFactor scale, Address::ScaleFactor scale1,
+                          Address::ScaleFactor scale2, Register index, int ae);
   // Compare strings.
   void string_compare(Register str1, Register str2,
                       Register cnt1, Register cnt2, Register result,
-                      XMMRegister vec1);
+                      XMMRegister vec1, int ae);
 
-  // Compare char[] arrays.
-  void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2,
-                          Register limit, Register result, Register chr,
-                          XMMRegister vec1, XMMRegister vec2);
+  // Search for Non-ASCII character (Negative byte value) in a byte array,
+  // return true if it has any and false otherwise.
+  void has_negatives(Register ary1, Register len,
+                     Register result, Register tmp1,
+                     XMMRegister vec1, XMMRegister vec2);
+
+  // Compare char[] or byte[] arrays.
+  void arrays_equals(bool is_array_equ, Register ary1, Register ary2,
+                     Register limit, Register result, Register chr,
+                     XMMRegister vec1, XMMRegister vec2, bool is_char);
+
+#endif
 
   // Fill primitive arrays
   void generate_fill(BasicType t, bool aligned,
@@ -1332,6 +1349,15 @@
   void fold_8bit_crc32(Register crc, Register table, Register tmp);
   void fold_8bit_crc32(XMMRegister crc, Register table, XMMRegister xtmp, Register tmp);
 
+  // Compress char[] array to byte[].
+  void char_array_compress(Register src, Register dst, Register len,
+                           XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3,
+                           XMMRegister tmp4, Register tmp5, Register result);
+
+  // Inflate byte[] array to char[].
+  void byte_array_inflate(Register src, Register dst, Register len,
+                          XMMRegister tmp1, Register tmp2);
+
 #undef VIRTUAL
 
 };
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -63,7 +63,7 @@
 void MethodHandles::verify_klass(MacroAssembler* _masm,
                                  Register obj, SystemDictionary::WKID klass_id,
                                  const char* error_message) {
-  Klass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
+  InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
   KlassHandle klass = SystemDictionary::well_known_klass(klass_id);
   Register temp = rdi;
   Register temp2 = noreg;
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1502,7 +1502,7 @@
 //    return to caller
 //
 nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
-                                                methodHandle method,
+                                                const methodHandle& method,
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1694,7 +1694,7 @@
 };
 
 static void verify_oop_args(MacroAssembler* masm,
-                            methodHandle method,
+                            const methodHandle& method,
                             const BasicType* sig_bt,
                             const VMRegPair* regs) {
   Register temp_reg = rbx;  // not part of any compiled calling seq
@@ -1804,7 +1804,7 @@
 //    return to caller
 //
 nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
-                                                methodHandle method,
+                                                const methodHandle& method,
                                                 int compile_id,
                                                 BasicType* in_sig_bt,
                                                 VMRegPair* in_regs,
--- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -82,6 +82,7 @@
   declare_constant(VM_Version::CPU_AVX512CD)                        \
   declare_constant(VM_Version::CPU_AVX512BW)
 
-#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
+  declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL)
 
 #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Jul 05 21:00:20 2017 +0200
@@ -11435,16 +11435,62 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
-                        eAXRegI result, regD tmp1, eFlagsReg cr) %{
+instruct string_compareL(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
+                         eAXRegI result, regD tmp1, eFlagsReg cr) %{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
   match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
   effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
 
-  format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
+  ins_encode %{
+    __ string_compare($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register, $result$$Register,
+                      $tmp1$$XMMRegister, StrIntrinsicNode::LL);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_compareU(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
+                         eAXRegI result, regD tmp1, eFlagsReg cr) %{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+
+  format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
   ins_encode %{
     __ string_compare($str1$$Register, $str2$$Register,
                       $cnt1$$Register, $cnt2$$Register, $result$$Register,
-                      $tmp1$$XMMRegister);
+                      $tmp1$$XMMRegister, StrIntrinsicNode::UU);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_compareLU(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
+                          eAXRegI result, regD tmp1, eFlagsReg cr) %{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
+  ins_encode %{
+    __ string_compare($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register, $result$$Register,
+                      $tmp1$$XMMRegister, StrIntrinsicNode::LU);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_compareUL(eSIRegP str1, eDXRegI cnt1, eDIRegP str2, eCXRegI cnt2,
+                          eAXRegI result, regD tmp1, eFlagsReg cr) %{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
+  ins_encode %{
+    __ string_compare($str2$$Register, $str1$$Register,
+                      $cnt2$$Register, $cnt1$$Register, $result$$Register,
+                      $tmp1$$XMMRegister, StrIntrinsicNode::UL);
   %}
   ins_pipe( pipe_slow );
 %}
@@ -11457,21 +11503,78 @@
 
   format %{ "String Equals $str1,$str2,$cnt -> $result    // KILL $tmp1, $tmp2, $tmp3" %}
   ins_encode %{
-    __ char_arrays_equals(false, $str1$$Register, $str2$$Register,
-                          $cnt$$Register, $result$$Register, $tmp3$$Register,
-                          $tmp1$$XMMRegister, $tmp2$$XMMRegister);
+    __ arrays_equals(false, $str1$$Register, $str2$$Register,
+                     $cnt$$Register, $result$$Register, $tmp3$$Register,
+                     $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */);
+  %} 
+
+  ins_pipe( pipe_slow );
+%}
+
+// fast search of substring with known size.
+instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
+                             eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
+  match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
+  effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
+
+  format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result   // KILL $vec, $cnt1, $cnt2, $tmp" %}
+  ins_encode %{
+    int icnt2 = (int)$int_cnt2$$constant;
+    if (icnt2 >= 16) {
+      // IndexOf for constant substrings with size >= 16 elements
+      // which don't need to be loaded through stack.
+      __ string_indexofC8($str1$$Register, $str2$$Register,
+                          $cnt1$$Register, $cnt2$$Register,
+                          icnt2, $result$$Register,
+                          $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
+    } else {
+      // Small strings are loaded through stack if they cross page boundary.
+      __ string_indexof($str1$$Register, $str2$$Register,
+                        $cnt1$$Register, $cnt2$$Register,
+                        icnt2, $result$$Register,
+                        $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
+    }
   %}
   ins_pipe( pipe_slow );
 %}
 
 // fast search of substring with known size.
-instruct string_indexof_con(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
-                            eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
-  predicate(UseSSE42Intrinsics);
+instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
+                             eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
   match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
   effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
 
-  format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result   // KILL $vec, $cnt1, $cnt2, $tmp" %}
+  format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result   // KILL $vec, $cnt1, $cnt2, $tmp" %}
+  ins_encode %{
+    int icnt2 = (int)$int_cnt2$$constant;
+    if (icnt2 >= 8) {
+      // IndexOf for constant substrings with size >= 8 elements
+      // which don't need to be loaded through stack.
+      __ string_indexofC8($str1$$Register, $str2$$Register,
+                          $cnt1$$Register, $cnt2$$Register,
+                          icnt2, $result$$Register,
+                          $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
+    } else {
+      // Small strings are loaded through stack if they cross page boundary.
+      __ string_indexof($str1$$Register, $str2$$Register,
+                        $cnt1$$Register, $cnt2$$Register,
+                        icnt2, $result$$Register,
+                        $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
+    }
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+// fast search of substring with known size.
+instruct string_indexof_conUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
+                             eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
+  match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
+  effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
+
+  format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result   // KILL $vec, $cnt1, $cnt2, $tmp" %}
   ins_encode %{
     int icnt2 = (int)$int_cnt2$$constant;
     if (icnt2 >= 8) {
@@ -11480,47 +11583,154 @@
       __ string_indexofC8($str1$$Register, $str2$$Register,
                           $cnt1$$Register, $cnt2$$Register,
                           icnt2, $result$$Register,
-                          $vec$$XMMRegister, $tmp$$Register);
+                          $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
     } else {
       // Small strings are loaded through stack if they cross page boundary.
       __ string_indexof($str1$$Register, $str2$$Register,
                         $cnt1$$Register, $cnt2$$Register,
                         icnt2, $result$$Register,
-                        $vec$$XMMRegister, $tmp$$Register);
+                        $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
     }
   %}
   ins_pipe( pipe_slow );
 %}
 
-instruct string_indexof(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
-                        eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
-  predicate(UseSSE42Intrinsics);
+instruct string_indexofL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
+                         eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
   match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
   effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
 
-  format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result   // KILL all" %}
+  format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL all" %}
   ins_encode %{
     __ string_indexof($str1$$Register, $str2$$Register,
                       $cnt1$$Register, $cnt2$$Register,
                       (-1), $result$$Register,
-                      $vec$$XMMRegister, $tmp$$Register);
+                      $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_indexofU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
+                         eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
+  match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
+
+  format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL all" %}
+  ins_encode %{
+    __ string_indexof($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register,
+                      (-1), $result$$Register,
+                      $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_indexofUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
+                         eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
+  match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
+
+  format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL all" %}
+  ins_encode %{
+    __ string_indexof($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register,
+                      (-1), $result$$Register,
+                      $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_indexofU_char(eDIRegP str1, eDXRegI cnt1, eAXRegI ch,
+                              eBXRegI result, regD vec1, regD vec2, regD vec3, eCXRegI tmp, eFlagsReg cr) %{
+  predicate(UseSSE42Intrinsics);
+  match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
+  effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
+  format %{ "String IndexOf char[] $str1,$cnt1,$ch -> $result   // KILL all" %}
+  ins_encode %{
+    __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
+                           $vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register);
   %}
   ins_pipe( pipe_slow );
 %}
 
 // fast array equals
-instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
-                      regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
+instruct array_equalsB(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
+                       regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
 %{
+  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
+  match(Set result (AryEq ary1 ary2));
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
+  //ins_cost(300);
+
+  format %{ "Array Equals byte[] $ary1,$ary2 -> $result   // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
+  ins_encode %{
+    __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
+                     $tmp3$$Register, $result$$Register, $tmp4$$Register,
+                     $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct array_equalsC(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
+                       regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
+%{
+  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
   match(Set result (AryEq ary1 ary2));
   effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
   //ins_cost(300);
 
-  format %{ "Array Equals $ary1,$ary2 -> $result   // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
-  ins_encode %{
-    __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register,
-                          $tmp3$$Register, $result$$Register, $tmp4$$Register,
-                          $tmp1$$XMMRegister, $tmp2$$XMMRegister);
+  format %{ "Array Equals char[] $ary1,$ary2 -> $result   // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
+  ins_encode %{
+    __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
+                     $tmp3$$Register, $result$$Register, $tmp4$$Register,
+                     $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct has_negatives(eSIRegP ary1, eCXRegI len, eAXRegI result,
+                      regD tmp1, regD tmp2, eBXRegI tmp3, eFlagsReg cr)
+%{
+  match(Set result (HasNegatives ary1 len));
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
+
+  format %{ "has negatives byte[] $ary1,$len -> $result   // KILL $tmp1, $tmp2, $tmp3" %}
+  ins_encode %{
+    __ has_negatives($ary1$$Register, $len$$Register,
+                     $result$$Register, $tmp3$$Register,
+                     $tmp1$$XMMRegister, $tmp2$$XMMRegister);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+// fast char[] to byte[] compression
+instruct string_compress(eSIRegP src, eDIRegP dst, eDXRegI len, regD tmp1, regD tmp2, regD tmp3, regD tmp4,
+                         eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{
+  match(Set result (StrCompressedCopy src (Binary dst len)));
+  effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
+
+  format %{ "String Compress $src,$dst -> $result    // KILL RAX, RCX, RDX" %}
+  ins_encode %{
+    __ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
+                           $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
+                           $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+// fast byte[] to char[] inflation
+instruct string_inflate(Universe dummy, eSIRegP src, eDIRegP dst, eDXRegI len,
+                        regD tmp1, eCXRegI tmp2, eFlagsReg cr) %{
+  match(Set dummy (StrInflatedCopy src (Binary dst len)));
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
+
+  format %{ "String Inflate $src,$dst    // KILL $tmp1, $tmp2" %}
+  ins_encode %{
+    __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
+                          $tmp1$$XMMRegister, $tmp2$$Register);
   %}
   ins_pipe( pipe_slow );
 %}
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Jul 05 21:00:20 2017 +0200
@@ -10447,30 +10447,108 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
-                        rax_RegI result, regD tmp1, rFlagsReg cr)
-%{
+instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
+                         rax_RegI result, regD tmp1, rFlagsReg cr)
+%{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
   match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
   effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
 
-  format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
+  ins_encode %{
+    __ string_compare($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register, $result$$Register,
+                      $tmp1$$XMMRegister, StrIntrinsicNode::LL);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
+                         rax_RegI result, regD tmp1, rFlagsReg cr)
+%{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+
+  format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
   ins_encode %{
     __ string_compare($str1$$Register, $str2$$Register,
                       $cnt1$$Register, $cnt2$$Register, $result$$Register,
-                      $tmp1$$XMMRegister);
+                      $tmp1$$XMMRegister, StrIntrinsicNode::UU);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
+                          rax_RegI result, regD tmp1, rFlagsReg cr)
+%{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
+  ins_encode %{
+    __ string_compare($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register, $result$$Register,
+                      $tmp1$$XMMRegister, StrIntrinsicNode::LU);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2,
+                          rax_RegI result, regD tmp1, rFlagsReg cr)
+%{
+  predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
+  match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+
+  format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL $tmp1" %}
+  ins_encode %{
+    __ string_compare($str2$$Register, $str1$$Register,
+                      $cnt2$$Register, $cnt1$$Register, $result$$Register,
+                      $tmp1$$XMMRegister, StrIntrinsicNode::UL);
   %}
   ins_pipe( pipe_slow );
 %}
 
 // fast search of substring with known size.
-instruct string_indexof_con(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
-                            rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
-%{
-  predicate(UseSSE42Intrinsics);
+instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
+                             rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
+%{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
   match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
   effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
 
-  format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result   // KILL $vec, $cnt1, $cnt2, $tmp" %}
+  format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result   // KILL $vec, $cnt1, $cnt2, $tmp" %}
+  ins_encode %{
+    int icnt2 = (int)$int_cnt2$$constant;
+    if (icnt2 >= 16) {
+      // IndexOf for constant substrings with size >= 16 elements
+      // which don't need to be loaded through stack.
+      __ string_indexofC8($str1$$Register, $str2$$Register,
+                          $cnt1$$Register, $cnt2$$Register,
+                          icnt2, $result$$Register,
+                          $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
+    } else {
+      // Small strings are loaded through stack if they cross page boundary.
+      __ string_indexof($str1$$Register, $str2$$Register,
+                        $cnt1$$Register, $cnt2$$Register,
+                        icnt2, $result$$Register,
+                        $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
+    }
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+// fast search of substring with known size.
+instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
+                             rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
+%{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
+  match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
+  effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
+
+  format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result   // KILL $vec, $cnt1, $cnt2, $tmp" %}
   ins_encode %{
     int icnt2 = (int)$int_cnt2$$constant;
     if (icnt2 >= 8) {
@@ -10479,31 +10557,108 @@
       __ string_indexofC8($str1$$Register, $str2$$Register,
                           $cnt1$$Register, $cnt2$$Register,
                           icnt2, $result$$Register,
-                          $vec$$XMMRegister, $tmp$$Register);
+                          $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
+    } else {
+      // Small strings are loaded through stack if they cross page boundary.
+      __ string_indexof($str1$$Register, $str2$$Register,
+                        $cnt1$$Register, $cnt2$$Register,
+                        icnt2, $result$$Register,
+                        $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
+    }
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+// fast search of substring with known size.
+instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
+                             rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
+%{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
+  match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
+  effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
+
+  format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result   // KILL $vec, $cnt1, $cnt2, $tmp" %}
+  ins_encode %{
+    int icnt2 = (int)$int_cnt2$$constant;
+    if (icnt2 >= 8) {
+      // IndexOf for constant substrings with size >= 8 elements
+      // which don't need to be loaded through stack.
+      __ string_indexofC8($str1$$Register, $str2$$Register,
+                          $cnt1$$Register, $cnt2$$Register,
+                          icnt2, $result$$Register,
+                          $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
     } else {
       // Small strings are loaded through stack if they cross page boundary.
       __ string_indexof($str1$$Register, $str2$$Register,
                         $cnt1$$Register, $cnt2$$Register,
                         icnt2, $result$$Register,
-                        $vec$$XMMRegister, $tmp$$Register);
+                        $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
     }
   %}
   ins_pipe( pipe_slow );
 %}
 
-instruct string_indexof(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
-                        rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr)
-%{
-  predicate(UseSSE42Intrinsics);
+instruct string_indexofL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
+                         rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr)
+%{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
   match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
   effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
 
-  format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result   // KILL all" %}
+  format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL all" %}
   ins_encode %{
     __ string_indexof($str1$$Register, $str2$$Register,
                       $cnt1$$Register, $cnt2$$Register,
                       (-1), $result$$Register,
-                      $vec$$XMMRegister, $tmp$$Register);
+                      $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_indexofU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
+                         rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr)
+%{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
+  match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
+
+  format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL all" %}
+  ins_encode %{
+    __ string_indexof($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register,
+                      (-1), $result$$Register,
+                      $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_indexofUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
+                         rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr)
+%{
+  predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
+  match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
+  effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
+
+  format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result   // KILL all" %}
+  ins_encode %{
+    __ string_indexof($str1$$Register, $str2$$Register,
+                      $cnt1$$Register, $cnt2$$Register,
+                      (-1), $result$$Register,
+                      $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct string_indexofU_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch,
+                              rbx_RegI result, regD vec1, regD vec2, regD vec3, rcx_RegI tmp, rFlagsReg cr)
+%{
+  predicate(UseSSE42Intrinsics);
+  match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
+  effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
+  format %{ "String IndexOf char[] $str1,$cnt1,$ch -> $result   // KILL all" %}
+  ins_encode %{
+    __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
+                           $vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register);
   %}
   ins_pipe( pipe_slow );
 %}
@@ -10517,26 +10672,86 @@
 
   format %{ "String Equals $str1,$str2,$cnt -> $result    // KILL $tmp1, $tmp2, $tmp3" %}
   ins_encode %{
-    __ char_arrays_equals(false, $str1$$Register, $str2$$Register,
-                          $cnt$$Register, $result$$Register, $tmp3$$Register,
-                          $tmp1$$XMMRegister, $tmp2$$XMMRegister);
+    __ arrays_equals(false, $str1$$Register, $str2$$Register,
+                     $cnt$$Register, $result$$Register, $tmp3$$Register,
+                     $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */);
   %}
   ins_pipe( pipe_slow );
 %}
 
 // fast array equals
-instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
+instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
+                       regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
+%{
+  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
+  match(Set result (AryEq ary1 ary2));
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
+
+  format %{ "Array Equals byte[] $ary1,$ary2 -> $result   // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
+  ins_encode %{
+    __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
+                     $tmp3$$Register, $result$$Register, $tmp4$$Register,
+                     $tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
                       regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
 %{
+  predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
   match(Set result (AryEq ary1 ary2));
   effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
-  //ins_cost(300);
-
-  format %{ "Array Equals $ary1,$ary2 -> $result   // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
-  ins_encode %{
-    __ char_arrays_equals(true, $ary1$$Register, $ary2$$Register,
-                          $tmp3$$Register, $result$$Register, $tmp4$$Register,
-                          $tmp1$$XMMRegister, $tmp2$$XMMRegister);
+
+  format %{ "Array Equals char[] $ary1,$ary2 -> $result   // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
+  ins_encode %{
+    __ arrays_equals(true, $ary1$$Register, $ary2$$Register,
+                     $tmp3$$Register, $result$$Register, $tmp4$$Register,
+                     $tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+instruct has_negatives(rsi_RegP ary1, rcx_RegI len, rax_RegI result,
+                      regD tmp1, regD tmp2, rbx_RegI tmp3, rFlagsReg cr)
+%{
+  match(Set result (HasNegatives ary1 len));
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
+
+  format %{ "has negatives byte[] $ary1,$len -> $result   // KILL $tmp1, $tmp2, $tmp3" %}
+  ins_encode %{
+    __ has_negatives($ary1$$Register, $len$$Register,
+                     $result$$Register, $tmp3$$Register,
+                     $tmp1$$XMMRegister, $tmp2$$XMMRegister);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+// fast char[] to byte[] compression
+instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, regD tmp1, regD tmp2, regD tmp3, regD tmp4,
+                         rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
+  match(Set result (StrCompressedCopy src (Binary dst len)));
+  effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
+
+  format %{ "String Compress $src,$dst -> $result    // KILL RAX, RCX, RDX" %}
+  ins_encode %{
+    __ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
+                           $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
+                           $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+// fast byte[] to char[] inflation
+instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len,
+                        regD tmp1, rcx_RegI tmp2, rFlagsReg cr) %{
+  match(Set dummy (StrInflatedCopy src (Binary dst len)));
+  effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
+
+  format %{ "String Inflate $src,$dst    // KILL $tmp1, $tmp2" %}
+  ins_encode %{
+    __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
+                          $tmp1$$XMMRegister, $tmp2$$Register);
   %}
   ins_pipe( pipe_slow );
 %}
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -69,6 +69,9 @@
 
 define_pd_global(bool, PreserveFramePointer, false);
 
+// No performance work done here yet.
+define_pd_global(bool, CompactStrings, false);
+
 #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint)  \
                                                                             \
   product(bool, UseFastEmptyMethods, true,                                  \
--- a/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/cpu/zero/vm/sharedRuntime_zero.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -76,7 +76,7 @@
 }
 
 nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
-                                                methodHandle method,
+                                                const methodHandle& method,
                                                 int compile_id,
                                                 BasicType *sig_bt,
                                                 VMRegPair *regs,
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,15 +22,18 @@
  */
 package jdk.vm.ci.amd64;
 
-import static jdk.vm.ci.code.MemoryBarriers.*;
-import static jdk.vm.ci.code.Register.*;
+import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
+import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
+import static jdk.vm.ci.code.Register.SPECIAL;
 
-import java.nio.*;
-import java.util.*;
+import java.nio.ByteOrder;
+import java.util.EnumSet;
 
-import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.Register.RegisterCategory;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.PlatformKind;
 
 /**
  * Represents the AMD64 architecture.
@@ -65,9 +68,7 @@
         r8, r9, r10, r11, r12, r13, r14, r15
     };
 
-    private static final int XMM_REFERENCE_MAP_SHIFT = 2;
-
-    public static final RegisterCategory XMM = new RegisterCategory("XMM", cpuRegisters.length, XMM_REFERENCE_MAP_SHIFT);
+    public static final RegisterCategory XMM = new RegisterCategory("XMM");
 
     // XMM registers
     public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
@@ -79,8 +80,8 @@
     public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
     public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
 
-    public static final Register xmm8 =  new Register(24,  8, "xmm8",  XMM);
-    public static final Register xmm9 =  new Register(25,  9, "xmm9",  XMM);
+    public static final Register xmm8  = new Register(24,  8, "xmm8",  XMM);
+    public static final Register xmm9  = new Register(25,  9, "xmm9",  XMM);
     public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
     public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
     public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
@@ -88,28 +89,77 @@
     public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
     public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
 
-    public static final Register[] xmmRegisters = {
+    public static final Register xmm16 = new Register(32, 16, "xmm16", XMM);
+    public static final Register xmm17 = new Register(33, 17, "xmm17", XMM);
+    public static final Register xmm18 = new Register(34, 18, "xmm18", XMM);
+    public static final Register xmm19 = new Register(35, 19, "xmm19", XMM);
+    public static final Register xmm20 = new Register(36, 20, "xmm20", XMM);
+    public static final Register xmm21 = new Register(37, 21, "xmm21", XMM);
+    public static final Register xmm22 = new Register(38, 22, "xmm22", XMM);
+    public static final Register xmm23 = new Register(39, 23, "xmm23", XMM);
+
+    public static final Register xmm24 = new Register(40, 24, "xmm24", XMM);
+    public static final Register xmm25 = new Register(41, 25, "xmm25", XMM);
+    public static final Register xmm26 = new Register(42, 26, "xmm26", XMM);
+    public static final Register xmm27 = new Register(43, 27, "xmm27", XMM);
+    public static final Register xmm28 = new Register(44, 28, "xmm28", XMM);
+    public static final Register xmm29 = new Register(45, 29, "xmm29", XMM);
+    public static final Register xmm30 = new Register(46, 30, "xmm30", XMM);
+    public static final Register xmm31 = new Register(47, 31, "xmm31", XMM);
+
+    public static final Register[] xmmRegistersSSE = {
         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
     };
 
-    public static final Register[] cpuxmmRegisters = {
+    public static final Register[] xmmRegistersAVX512 = {
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
+        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31
+    };
+
+    public static final RegisterCategory MASK = new RegisterCategory("MASK", false);
+
+    public static final Register k0 = new Register(48, 0, "k0", MASK);
+    public static final Register k1 = new Register(49, 1, "k1", MASK);
+    public static final Register k2 = new Register(50, 2, "k2", MASK);
+    public static final Register k3 = new Register(51, 3, "k3", MASK);
+    public static final Register k4 = new Register(52, 4, "k4", MASK);
+    public static final Register k5 = new Register(53, 5, "k5", MASK);
+    public static final Register k6 = new Register(54, 6, "k6", MASK);
+    public static final Register k7 = new Register(55, 7, "k7", MASK);
+
+    public static final Register[] valueRegistersSSE = {
         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
     };
 
+    public static final Register[] valueRegistersAVX512 = {
+        rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
+        r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
+        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
+        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
+        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
+        k0, k1, k2, k3, k4, k5, k6, k7
+    };
+
     /**
      * Register used to construct an instruction-relative address.
      */
-    public static final Register rip = new Register(32, -1, "rip", SPECIAL);
+    public static final Register rip = new Register(56, -1, "rip", SPECIAL);
 
     public static final Register[] allRegisters = {
         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+        xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
+        xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
+        k0, k1, k2, k3, k4, k5, k6, k7,
         rip
     };
 
@@ -151,7 +201,8 @@
         AVX512PF,
         AVX512ER,
         AVX512CD,
-        AVX512BW
+        AVX512BW,
+        AVX512VL
     }
 
     private final EnumSet<CPUFeature> features;
@@ -166,11 +217,21 @@
 
     private final EnumSet<Flag> flags;
 
+    private final AMD64Kind largestKind;
+
     public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
-        super("AMD64", JavaKind.Long, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8);
+        super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, 8);
         this.features = features;
         this.flags = flags;
         assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
+
+        if (features.contains(CPUFeature.AVX512F)) {
+            largestKind = AMD64Kind.V512_QWORD;
+        } else if (features.contains(CPUFeature.AVX)) {
+            largestKind = AMD64Kind.V256_QWORD;
+        } else {
+            largestKind = AMD64Kind.V128_QWORD;
+        }
     }
 
     public EnumSet<CPUFeature> getFeatures() {
@@ -182,50 +243,60 @@
     }
 
     @Override
+    public Register[] getAvailableValueRegisters() {
+        if (features.contains(CPUFeature.AVX512F)) {
+            return valueRegistersAVX512;
+        } else {
+            return valueRegistersSSE;
+        }
+    }
+
+    @Override
     public PlatformKind getPlatformKind(JavaKind javaKind) {
-        if (javaKind.isObject()) {
-            return getWordKind();
-        } else {
-            return javaKind;
+        switch (javaKind) {
+            case Boolean:
+            case Byte:
+                return AMD64Kind.BYTE;
+            case Short:
+            case Char:
+                return AMD64Kind.WORD;
+            case Int:
+                return AMD64Kind.DWORD;
+            case Long:
+            case Object:
+                return AMD64Kind.QWORD;
+            case Float:
+                return AMD64Kind.SINGLE;
+            case Double:
+                return AMD64Kind.DOUBLE;
+            default:
+                return null;
         }
     }
 
     @Override
     public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
-        if (!(platformKind instanceof JavaKind)) {
-            return false;
+        AMD64Kind kind = (AMD64Kind) platformKind;
+        if (kind.isInteger()) {
+            return category.equals(CPU);
+        } else if (kind.isXMM()) {
+            return category.equals(XMM);
+        } else {
+            assert kind.isMask();
+            return category.equals(MASK);
         }
-
-        JavaKind kind = (JavaKind) platformKind;
-        if (category.equals(CPU)) {
-            switch (kind) {
-                case Boolean:
-                case Byte:
-                case Char:
-                case Short:
-                case Int:
-                case Long:
-                    return true;
-            }
-        } else if (category.equals(XMM)) {
-            switch (kind) {
-                case Float:
-                case Double:
-                    return true;
-            }
-        }
-
-        return false;
     }
 
     @Override
-    public PlatformKind getLargestStorableKind(RegisterCategory category) {
+    public AMD64Kind getLargestStorableKind(RegisterCategory category) {
         if (category.equals(CPU)) {
-            return JavaKind.Long;
+            return AMD64Kind.QWORD;
         } else if (category.equals(XMM)) {
-            return JavaKind.Double;
+            return largestKind;
+        } else if (category.equals(MASK)) {
+            return AMD64Kind.MASK64;
         } else {
-            return JavaKind.Illegal;
+            return null;
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64Kind.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.amd64;
+
+import jdk.vm.ci.meta.PlatformKind;
+
+public enum AMD64Kind implements PlatformKind {
+
+    // scalar
+    BYTE(1),
+    WORD(2),
+    DWORD(4),
+    QWORD(8),
+    SINGLE(4),
+    DOUBLE(8),
+
+    // SSE2
+    V32_BYTE(4, BYTE),
+    V32_WORD(4, WORD),
+    V64_BYTE(8, BYTE),
+    V64_WORD(8, WORD),
+    V64_DWORD(8, DWORD),
+    V128_BYTE(16, BYTE),
+    V128_WORD(16, WORD),
+    V128_DWORD(16, DWORD),
+    V128_QWORD(16, QWORD),
+    V128_SINGLE(16, SINGLE),
+    V128_DOUBLE(16, DOUBLE),
+
+    // AVX
+    V256_BYTE(32, BYTE),
+    V256_WORD(32, WORD),
+    V256_DWORD(32, DWORD),
+    V256_QWORD(32, QWORD),
+    V256_SINGLE(32, SINGLE),
+    V256_DOUBLE(32, DOUBLE),
+
+    // AVX512
+    V512_BYTE(64, BYTE),
+    V512_WORD(64, WORD),
+    V512_DWORD(64, DWORD),
+    V512_QWORD(64, QWORD),
+    V512_SINGLE(64, SINGLE),
+    V512_DOUBLE(64, DOUBLE),
+
+    MASK8(1),
+    MASK16(2),
+    MASK32(4),
+    MASK64(8);
+
+    private final int size;
+    private final int vectorLength;
+
+    private final AMD64Kind scalar;
+    private final EnumKey<AMD64Kind> key = new EnumKey<>(this);
+
+    private AMD64Kind(int size) {
+        this.size = size;
+        this.scalar = this;
+        this.vectorLength = 1;
+    }
+
+    private AMD64Kind(int size, AMD64Kind scalar) {
+        this.size = size;
+        this.scalar = scalar;
+
+        assert size % scalar.size == 0;
+        this.vectorLength = size / scalar.size;
+    }
+
+    public AMD64Kind getScalar() {
+        return scalar;
+    }
+
+    public int getSizeInBytes() {
+        return size;
+    }
+
+    public int getVectorLength() {
+        return vectorLength;
+    }
+
+    public Key getKey() {
+        return key;
+    }
+
+    public boolean isInteger() {
+        switch (this) {
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case QWORD:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public boolean isXMM() {
+        switch (this) {
+            case SINGLE:
+            case DOUBLE:
+            case V32_BYTE:
+            case V32_WORD:
+            case V64_BYTE:
+            case V64_WORD:
+            case V64_DWORD:
+            case V128_BYTE:
+            case V128_WORD:
+            case V128_DWORD:
+            case V128_QWORD:
+            case V128_SINGLE:
+            case V128_DOUBLE:
+            case V256_BYTE:
+            case V256_WORD:
+            case V256_DWORD:
+            case V256_QWORD:
+            case V256_SINGLE:
+            case V256_DOUBLE:
+            case V512_BYTE:
+            case V512_WORD:
+            case V512_DWORD:
+            case V512_QWORD:
+            case V512_SINGLE:
+            case V512_DOUBLE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public boolean isMask() {
+        switch (this) {
+            case MASK8:
+            case MASK16:
+            case MASK32:
+            case MASK64:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public char getTypeChar() {
+        switch (this) {
+            case BYTE:
+                return 'b';
+            case WORD:
+                return 'w';
+            case DWORD:
+                return 'd';
+            case QWORD:
+                return 'q';
+            case SINGLE:
+                return 'S';
+            case DOUBLE:
+                return 'D';
+            case V32_BYTE:
+            case V32_WORD:
+            case V64_BYTE:
+            case V64_WORD:
+            case V64_DWORD:
+                return 'v';
+            case V128_BYTE:
+            case V128_WORD:
+            case V128_DWORD:
+            case V128_QWORD:
+            case V128_SINGLE:
+            case V128_DOUBLE:
+                return 'x';
+            case V256_BYTE:
+            case V256_WORD:
+            case V256_DWORD:
+            case V256_QWORD:
+            case V256_SINGLE:
+            case V256_DOUBLE:
+                return 'y';
+            case V512_BYTE:
+            case V512_WORD:
+            case V512_DWORD:
+            case V512_QWORD:
+            case V512_SINGLE:
+            case V512_DOUBLE:
+                return 'z';
+            case MASK8:
+            case MASK16:
+            case MASK32:
+            case MASK64:
+                return 'k';
+            default:
+                return '-';
+        }
+    }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.vm.ci.code;
-
-/**
- * Abstract base class that represents a platform specific address.
- */
-public abstract class AbstractAddress {
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,11 +22,12 @@
  */
 package jdk.vm.ci.code;
 
-import java.nio.*;
-import java.util.*;
+import java.nio.ByteOrder;
+import java.util.Arrays;
 
 import jdk.vm.ci.code.Register.RegisterCategory;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.PlatformKind;
 
 /**
  * Represents a CPU architecture, including information such as its endianness, CPU registers, word
@@ -35,13 +36,6 @@
 public abstract class Architecture {
 
     /**
-     * The number of entries required in a {@link ReferenceMap} covering all the registers that may
-     * store references. The index of a register in the reference map is given by
-     * {@link Register#getReferenceMapIndex()}.
-     */
-    private final int registerReferenceMapSize;
-
-    /**
      * The architecture specific type of a native word.
      */
     private final PlatformKind wordKind;
@@ -85,7 +79,7 @@
     private final int returnAddressSize;
 
     protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset,
-                    int registerReferenceMapSize, int returnAddressSize) {
+                    int returnAddressSize) {
         this.name = name;
         this.registers = registers;
         this.wordKind = wordKind;
@@ -93,7 +87,6 @@
         this.unalignedMemoryAccess = unalignedMemoryAccess;
         this.implicitMemoryBarriers = implicitMemoryBarriers;
         this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
-        this.registerReferenceMapSize = registerReferenceMapSize;
         this.returnAddressSize = returnAddressSize;
     }
 
@@ -107,10 +100,6 @@
         return getName().toLowerCase();
     }
 
-    public int getRegisterReferenceMapSize() {
-        return registerReferenceMapSize;
-    }
-
     /**
      * Gets the natural size of words (typically registers and pointers) of this architecture, in
      * bytes.
@@ -131,13 +120,23 @@
     }
 
     /**
-     * Gets an array of all available registers on this architecture. The index of each register in
-     * this array is equal to its {@linkplain Register#number number}.
+     * Gets an array of all registers that exist on this architecture. This contains all registers
+     * that exist in the specification of this architecture. Not all of them may be available on
+     * this particular architecture instance. The index of each register in this array is equal to
+     * its {@linkplain Register#number number}.
      */
     public Register[] getRegisters() {
         return registers.clone();
     }
 
+    /**
+     * Gets an array of all registers available for storing values on this architecture. This may be
+     * a subset of {@link #getRegisters()}, depending on the capabilities of this particular CPU.
+     */
+    public Register[] getAvailableValueRegisters() {
+        return getRegisters();
+    }
+
     public ByteOrder getByteOrder() {
         return byteOrder;
     }
@@ -207,7 +206,6 @@
                 assert this.byteOrder.equals(that.byteOrder);
                 assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
                 assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
-                assert this.registerReferenceMapSize == that.registerReferenceMapSize;
                 assert Arrays.equals(this.registers, that.registers);
                 assert this.returnAddressSize == that.returnAddressSize;
                 assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.Locale;
 
 /**
  * Exception thrown when the compiler refuses to compile a method because of problems with the
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,12 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.Arrays;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.Value;
 
 /**
  * Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,9 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.Objects;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
  * Represents a code position, that is, a chain of inlined methods with bytecode locations, that is
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,10 @@
  */
 package jdk.vm.ci.code;
 
-import static jdk.vm.ci.code.ValueUtil.*;
-
-import jdk.vm.ci.meta.*;
+import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
 
 /**
  * A calling convention describes the locations in which the arguments for a call are placed and the
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,14 @@
  */
 package jdk.vm.ci.code;
 
-import jdk.vm.ci.code.CompilationResult.*;
-import jdk.vm.ci.code.DataSection.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.CompilationResult.Call;
+import jdk.vm.ci.code.CompilationResult.DataPatch;
+import jdk.vm.ci.code.CompilationResult.Mark;
+import jdk.vm.ci.code.DataSection.Data;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.SpeculationLog;
 
 /**
  * Access to code cache related details and requirements.
@@ -32,26 +37,62 @@
 public interface CodeCacheProvider {
 
     /**
-     * Adds the given compilation result as an implementation of the given method without making it
-     * the default implementation.
+     * Installs code for a given method based on a given compilation result without making it the
+     * default implementation of the method.
      *
-     * @param method a method to which the executable code is begin added
+     * @param method a method implemented by the installed code
      * @param compResult the compilation result to be added
-     * @param speculationLog the speculation log to be used
-     * @return a reference to the compiled and ready-to-run code or throws a
-     *         {@link BailoutException} if the code installation failed
+     * @param log the speculation log to be used
+     * @param installedCode a predefined {@link InstalledCode} object to use as a reference to the
+     *            installed code. If {@code null}, a new {@link InstalledCode} object will be
+     *            created.
+     * @return a reference to the ready-to-run code
+     * @throws BailoutException if the code installation failed
      */
-    InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode);
+    default InstalledCode addCode(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode installedCode) {
+        return installCode(new CompilationRequest(method), compResult, installedCode, log, false);
+    }
 
     /**
-     * Sets the given compilation result as the default implementation of the given method.
+     * Installs code for a given method based on a given compilation result and makes it the default
+     * implementation of the method.
      *
-     * @param method a method to which the executable code is begin added
+     * @param method a method implemented by the installed code and for which the installed code
+     *            becomes the default implementation
+     * @param compResult the compilation result to be added
+     * @return a reference to the ready-to-run code
+     * @throws BailoutException if the code installation failed
+     */
+    default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompilationResult compResult) {
+        return installCode(new CompilationRequest(method), compResult, null, null, true);
+    }
+
+    /**
+     * Installs code based on a given compilation result.
+     *
+     * @param compRequest details of the method compiled to produce {@code compResult} or
+     *            {@code null} if the input to {@code compResult} was not a
+     *            {@link ResolvedJavaMethod}
      * @param compResult the compilation result to be added
-     * @return a reference to the compiled and ready-to-run code or null if the code installation
-     *         failed
+     * @param installedCode a pre-allocated {@link InstalledCode} object to use as a reference to
+     *            the installed code. If {@code null}, a new {@link InstalledCode} object will be
+     *            created.
+     * @param log the speculation log to be used
+     * @param isDefault specifies if the installed code should be made the default implementation of
+     *            {@code compRequest.getMethod()}. The default implementation for a method is the
+     *            code executed for standard calls to the method. This argument is ignored if
+     *            {@code compRequest == null}.
+     * @return a reference to the compiled and ready-to-run installed code
+     * @throws BailoutException if the code installation failed
      */
-    InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult);
+    InstalledCode installCode(CompilationRequest compRequest, CompilationResult compResult, InstalledCode installedCode, SpeculationLog log, boolean isDefault);
+
+    /**
+     * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be
+     * raised the next time {@code installedCode} is
+     * {@linkplain InstalledCode#executeVarargs(Object...) executed}.
+     */
+    void invalidateInstalledCode(InstalledCode installedCode);
 
     /**
      * Gets a name for a {@link Mark} mark.
@@ -102,4 +143,16 @@
      * Create a new speculation log for the target runtime.
      */
     SpeculationLog createSpeculationLog();
+
+    /**
+     * Returns the maximum absolute offset of a PC relative call to a given address from any
+     * position in the code cache or -1 when not applicable. Intended for determining the required
+     * size of address/offset fields.
+     */
+    long getMaxCallTargetOffset(long address);
+
+    /**
+     * Determines if debug info should also be emitted at non-safepoint locations.
+     */
+    boolean shouldDebugNonSafepoints();
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,15 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.MetaUtil;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.Signature;
 
 /**
  * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.code} and its clients.
@@ -323,49 +329,12 @@
     public interface RefMapFormatter {
 
         String formatStackSlot(int frameRefMapIndex);
-
-        String formatRegister(int regRefMapIndex);
     }
 
     /**
-     * Formats a location in a register reference map.
+     * Formats a location present in a reference map.
      */
-    public static class DefaultRegFormatter implements RefMapFormatter {
-
-        private final Register[] registers;
-
-        public DefaultRegFormatter(Architecture arch) {
-            registers = new Register[arch.getRegisterReferenceMapSize()];
-            for (Register r : arch.getRegisters()) {
-                if (r.getReferenceMapIndex() >= 0) {
-                    registers[r.getReferenceMapIndex()] = r;
-                }
-            }
-        }
-
-        public String formatStackSlot(int frameRefMapIndex) {
-            return null;
-        }
-
-        public String formatRegister(int regRefMapIndex) {
-            int i = regRefMapIndex;
-            int idx = 0;
-            while (registers[i] == null) {
-                i--;
-                idx++;
-            }
-            if (idx == 0) {
-                return registers[i].toString();
-            } else {
-                return String.format("%s+%d", registers[i].toString(), idx);
-            }
-        }
-    }
-
-    /**
-     * Formats a location present in a register or frame reference map.
-     */
-    public static class DefaultRefMapFormatter extends DefaultRegFormatter {
+    public static class DefaultRefMapFormatter implements RefMapFormatter {
 
         /**
          * The size of a stack slot.
@@ -383,8 +352,7 @@
          */
         public final int refMapToFPOffset;
 
-        public DefaultRefMapFormatter(Architecture arch, int slotSize, Register fp, int refMapToFPOffset) {
-            super(arch);
+        public DefaultRefMapFormatter(int slotSize, Register fp, int refMapToFPOffset) {
             this.slotSize = slotSize;
             this.fp = fp;
             this.refMapToFPOffset = refMapToFPOffset;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationRequest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Represents a request to compile a method.
+ */
+public class CompilationRequest {
+
+    private final ResolvedJavaMethod method;
+
+    private final int entryBCI;
+
+    /**
+     * Creates a request to compile a method starting at its entry point.
+     *
+     * @param method the method to be compiled
+     */
+    public CompilationRequest(ResolvedJavaMethod method) {
+        this(method, -1);
+    }
+
+    /**
+     * Creates a request to compile a method starting at a given BCI.
+     *
+     * @param method the method to be compiled
+     * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
+     *            method's entry point
+     */
+    public CompilationRequest(ResolvedJavaMethod method, int entryBCI) {
+        assert method != null;
+        this.method = method;
+        this.entryBCI = entryBCI;
+    }
+
+    /**
+     * Gets the method to be compiled.
+     */
+    public ResolvedJavaMethod getMethod() {
+        return method;
+    }
+
+    /**
+     * Gets the bytecode index (BCI) at which to start compiling where -1 denotes a non-OSR
+     * compilation request and all other values denote an on stack replacement (OSR) compilation
+     * request.
+     */
+    public int getEntryBCI() {
+        return entryBCI;
+    }
+
+    @Override
+    public String toString() {
+        return method.format("%H.%n(%p)@" + entryBCI);
+    }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,13 +22,24 @@
  */
 package jdk.vm.ci.code;
 
-import static java.util.Collections.*;
-import static jdk.vm.ci.meta.MetaUtil.*;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.unmodifiableList;
+import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.meta.Assumptions.*;
+import jdk.vm.ci.meta.Assumptions.Assumption;
+import jdk.vm.ci.meta.InvokeTarget;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.MetaUtil;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.VMConstant;
 
 /**
  * Represents the output from compiling a method, including the compiled machine code, associated
@@ -115,8 +126,8 @@
 
     public enum MetaSpaceAccessType {
         Move,
-        Store, // store only works for compressed oops (memory <- 32bit value). Compressed oops is
-               // not supported using AOT. TODO: Look at HotSpotStoreConstantOp
+        Store,  // store only works for compressed oops (memory <- 32bit value). Compressed oops is
+        // not supported using AOT. TODO: Look at HotSpotStoreConstantOp
         Compare; // HotSpotCompareMemoryConstantOp, HotSpotCompareConstantOp
 
         private MetaSpaceAccessType() {
@@ -128,13 +139,11 @@
      */
     public static final class MetaSpaceAccess extends Infopoint {
 
-        private static final long serialVersionUID = 1701958512608684706L;
-
         /**
          * Metaspace reference.
          */
         public final Object reference; // Object here is a HotSpotResolvedObjectType or a
-                                       // HotSpotMetaSpaceConstant
+        // HotSpotMetaSpaceConstant
 
         public final MetaSpaceAccessType type;
 
@@ -296,6 +305,15 @@
             }
             return false;
         }
+
+        @Override
+        public String toString() {
+            if (initialized) {
+                return String.format("DataSection[0x%x]", offset);
+            } else {
+                return "DataSection[?]";
+            }
+        }
     }
 
     /**
@@ -528,8 +546,6 @@
         }
     }
 
-    private int id = -1;
-
     /**
      * Specifies whether this compilation is a {@code +ImmutableCode} {@code +GeneratePIC}
      * compilation.
@@ -612,7 +628,6 @@
             CompilationResult that = (CompilationResult) obj;
             // @formatter:off
             if (this.entryBCI == that.entryBCI &&
-                this.id == that.id &&
                 this.customStackAreaOffset == that.customStackAreaOffset &&
                 this.totalFrameSize == that.totalFrameSize &&
                 this.targetCodeSize == that.targetCodeSize &&
@@ -633,20 +648,6 @@
     }
 
     /**
-     * @return the compile id
-     */
-    public int getId() {
-        return id;
-    }
-
-    /**
-     * @param id the compile id to set
-     */
-    public void setId(int id) {
-        this.id = id;
-    }
-
-    /**
      * @return true is this is a {@code +ImmutableCode} {@code +GeneratePIC} compilation, false
      *         otherwise.
      */
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,15 +22,18 @@
  */
 package jdk.vm.ci.code;
 
-import static jdk.vm.ci.meta.MetaUtil.*;
+import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
 
-import java.nio.*;
-import java.util.*;
-import java.util.function.*;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.function.Consumer;
 
-import jdk.vm.ci.code.CompilationResult.*;
-import jdk.vm.ci.code.DataSection.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.CompilationResult.DataPatch;
+import jdk.vm.ci.code.CompilationResult.DataSectionReference;
+import jdk.vm.ci.code.DataSection.Data;
+import jdk.vm.ci.meta.SerializableConstant;
 
 public final class DataSection implements Iterable<Data> {
 
@@ -176,11 +179,27 @@
      */
     public DataSectionReference insertData(Data data) {
         assert !finalLayout;
-        if (data.ref == null) {
-            data.ref = new DataSectionReference();
+        synchronized (data) {
+            if (data.ref == null) {
+                data.ref = new DataSectionReference();
+                dataItems.add(data);
+            }
+            return data.ref;
+        }
+    }
+
+    /**
+     * Transfers all {@link Data} from the provided other {@link DataSection} to this
+     * {@link DataSection}, and empties the other section.
+     */
+    public void addAll(DataSection other) {
+        assert !finalLayout && !other.finalLayout;
+
+        for (Data data : other.dataItems) {
+            assert data.ref != null;
             dataItems.add(data);
         }
-        return data.ref;
+        other.dataItems.clear();
     }
 
     /**
@@ -195,14 +214,16 @@
         dataItems.sort((a, b) -> a.alignment - b.alignment);
 
         int position = 0;
+        int alignment = 1;
         for (Data d : dataItems) {
-            sectionAlignment = lcm(sectionAlignment, d.alignment);
+            alignment = lcm(alignment, d.alignment);
             position = align(position, d.alignment);
 
             d.ref.setOffset(position);
             position += d.size;
         }
 
+        sectionAlignment = alignment;
         sectionSize = position;
     }
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.Objects;
 
 /**
  * Represents the debugging information for a particular point of execution. This information
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,14 +29,19 @@
 public class InstalledCode {
 
     /**
-     * Raw address of this code blob.
+     * Raw address address of entity representing this installed code.
      */
-    private long address;
+    protected long address;
+
+    /**
+     * Raw address of entryPoint of this installed code.
+     */
+    protected long entryPoint;
 
     /**
      * Counts how often the address field was reassigned.
      */
-    private long version;
+    protected long version;
 
     protected final String name;
 
@@ -44,27 +49,29 @@
         this.name = name;
     }
 
-    public final void setAddress(long address) {
-        this.address = address;
-        version++;
-    }
-
     /**
-     * @return the address of this code blob
+     * @return the address of entity representing this installed code.
      */
     public final long getAddress() {
         return address;
     }
 
     /**
-     * @return the address of this code blob
+     * @return the address of the normal entry point of the installed code.
+     */
+    public final long getEntryPoint() {
+        return entryPoint;
+    }
+
+    /**
+     * @return the version number of this installed code
      */
     public final long getVersion() {
         return version;
     }
 
     /**
-     * Returns the name of this code blob.
+     * Returns the name of this installed code.
      */
     public String getName() {
         return name;
@@ -79,10 +86,19 @@
     }
 
     /**
-     * Returns the number of instruction bytes for this code.
+     * @return true if the code represented by this object is still valid for invocation, false
+     *         otherwise (may happen due to deopt, etc.)
      */
-    public long getCodeSize() {
-        return 0;
+    public boolean isValid() {
+        return entryPoint != 0;
+    }
+
+    /**
+     * @return true if the code represented by this object still exists and might have live
+     *         activations, false otherwise (may happen due to deopt, etc.)
+     */
+    public boolean isAlive() {
+        return address != 0;
     }
 
     /**
@@ -93,17 +109,9 @@
     }
 
     /**
-     * @return true if the code represented by this object is still valid, false otherwise (may
-     *         happen due to deopt, etc.)
-     */
-    public boolean isValid() {
-        return address != 0;
-    }
-
-    /**
      * Invalidates this installed code such that any subsequent
      * {@linkplain #executeVarargs(Object...) invocation} will throw an
-     * {@link InvalidInstalledCodeException}.
+     * {@link InvalidInstalledCodeException} and all existing invocations will be deoptimized.
      */
     public void invalidate() {
         throw new UnsupportedOperationException();
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,8 @@
  */
 package jdk.vm.ci.code;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.LIRKind;
 
 /**
  * Represents a target machine register.
@@ -80,22 +81,15 @@
     public static class RegisterCategory {
 
         private final String name;
-
-        private final int referenceMapOffset;
-        private final int referenceMapShift;
+        private final boolean mayContainReference;
 
         public RegisterCategory(String name) {
-            this(name, 0, 0);
+            this(name, true);
         }
 
-        public RegisterCategory(String name, int referenceMapOffset) {
-            this(name, referenceMapOffset, 0);
-        }
-
-        public RegisterCategory(String name, int referenceMapOffset, int referenceMapShift) {
+        public RegisterCategory(String name, boolean mayContainReference) {
             this.name = name;
-            this.referenceMapOffset = referenceMapOffset;
-            this.referenceMapShift = referenceMapShift;
+            this.mayContainReference = mayContainReference;
         }
 
         @Override
@@ -112,7 +106,7 @@
         public boolean equals(Object obj) {
             if (obj instanceof RegisterCategory) {
                 RegisterCategory that = (RegisterCategory) obj;
-                return this.referenceMapOffset == that.referenceMapOffset && this.referenceMapShift == that.referenceMapShift && this.name.equals(that.name);
+                return this.name.equals(that.name);
             }
             return false;
         }
@@ -138,10 +132,10 @@
     }
 
     /**
-     * Get the start index of this register in the {@link ReferenceMap}.
+     * Determine whether this register needs to be part of the reference map.
      */
-    public int getReferenceMapIndex() {
-        return (encoding << registerCategory.referenceMapShift) + registerCategory.referenceMapOffset;
+    public boolean mayContainReference() {
+        return registerCategory.mayContainReference;
     }
 
     /**
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.Arrays;
 
 /**
  * A collection of register attributes. The specific attribute values for a register may be local to
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,8 +22,10 @@
  */
 package jdk.vm.ci.code;
 
-import jdk.vm.ci.code.CallingConvention.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.CallingConvention.Type;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.PlatformKind;
 
 /**
  * A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,11 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.TreeMap;
 
 /**
  * A map from registers to frame slots. This can be used to describe where callee saved registers
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,9 @@
  */
 package jdk.vm.ci.code;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.LIRKind;
 
 /**
  * Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,9 @@
  */
 package jdk.vm.ci.code;
 
-import static jdk.vm.ci.code.ValueUtil.*;
-
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.Value;
 
 /**
  * Represents lock information in the debug information.
@@ -32,10 +32,10 @@
 public final class StackLockValue implements JavaValue {
 
     private JavaValue owner;
-    private StackSlotValue slot;
+    private AllocatableValue slot;
     private final boolean eliminated;
 
-    public StackLockValue(JavaValue object, StackSlotValue slot, boolean eliminated) {
+    public StackLockValue(JavaValue object, AllocatableValue slot, boolean eliminated) {
         this.owner = object;
         this.slot = slot;
         this.eliminated = eliminated;
@@ -81,8 +81,7 @@
         return false;
     }
 
-    public void setSlot(StackSlotValue stackSlot) {
-        assert slot == null || (isVirtualStackSlot(slot) && (slot.equals(stackSlot) || isStackSlot(stackSlot))) : String.format("Can not set slot for %s to %s", this, stackSlot);
+    public void setSlot(AllocatableValue stackSlot) {
         slot = stackSlot;
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,13 +22,14 @@
  */
 package jdk.vm.ci.code;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.LIRKind;
 
 /**
  * Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an
  * incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}.
  */
-public final class StackSlot extends StackSlotValue {
+public final class StackSlot extends AllocatableValue {
 
     private final int offset;
     private final boolean addFrameSize;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlotValue.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2014, 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 jdk.vm.ci.code;
-
-import jdk.vm.ci.meta.*;
-
-/**
- * Common base class for {@linkplain StackSlot real} and {@linkplain VirtualStackSlot virtual} stack
- * slots.
- */
-public abstract class StackSlotValue extends AllocatableValue {
-
-    public StackSlotValue(LIRKind lirKind) {
-        super(lirKind);
-    }
-
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,10 @@
  */
 package jdk.vm.ci.code;
 
-import static jdk.vm.ci.meta.MetaUtil.*;
-
-import jdk.vm.ci.meta.*;
+import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.PlatformKind;
 
 /**
  * Represents the target machine for a compiler, including the CPU architecture, the size of
@@ -50,9 +51,9 @@
     public final int wordSize;
 
     /**
-     * The kind to be used for representing raw pointers and CPU registers.
+     * The {@link JavaKind} to be used for representing raw pointers and CPU registers in Java code.
      */
-    public final JavaKind wordKind;
+    public final JavaKind wordJavaKind;
 
     /**
      * The stack alignment requirement of the platform. For example, from Appendix D of <a
@@ -78,10 +79,12 @@
         this.arch = arch;
         this.isMP = isMP;
         this.wordSize = arch.getWordSize();
-        this.wordKind = JavaKind.fromWordSize(wordSize);
+        this.wordJavaKind = JavaKind.fromWordSize(wordSize);
         this.stackAlignment = stackAlignment;
         this.implicitNullCheckLimit = implicitNullCheckLimit;
         this.inlineObjects = inlineObjects;
+
+        assert arch.getPlatformKind(wordJavaKind).equals(arch.getWordKind());
     }
 
     @Override
@@ -101,7 +104,7 @@
                 this.inlineObjects == that.inlineObjects &&
                 this.isMP == that.isMP &&
                 this.stackAlignment == that.stackAlignment &&
-                this.wordKind.equals(that.wordKind) &&
+                this.wordJavaKind.equals(that.wordJavaKind) &&
                 this.wordSize == that.wordSize &&
                 this.arch.equals(that.arch)) {
                 return true;
@@ -116,10 +119,6 @@
         return identityHashCodeString(this);
     }
 
-    public int getSizeInBytes(PlatformKind kind) {
-        return kind.getSizeInBytes();
-    }
-
     public LIRKind getLIRKind(JavaKind javaKind) {
         PlatformKind platformKind = arch.getPlatformKind(javaKind);
         if (javaKind.isObject()) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/UnsignedMath.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2011, 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.
- */
-package jdk.vm.ci.code;
-
-import java.math.*;
-
-//JaCoCo Exclude
-
-/**
- * Utilities for unsigned comparisons. All methods have correct, but slow, standard Java
- * implementations so that they can be used with compilers not supporting the intrinsics.
- */
-public class UnsignedMath {
-
-    private static final long MASK = 0xffffffffL;
-
-    /**
-     * Unsigned comparison aboveThan for two numbers.
-     */
-    public static boolean aboveThan(int a, int b) {
-        return (a & MASK) > (b & MASK);
-    }
-
-    /**
-     * Unsigned comparison aboveOrEqual for two numbers.
-     */
-    public static boolean aboveOrEqual(int a, int b) {
-        return (a & MASK) >= (b & MASK);
-    }
-
-    /**
-     * Unsigned comparison belowThan for two numbers.
-     */
-    public static boolean belowThan(int a, int b) {
-        return (a & MASK) < (b & MASK);
-    }
-
-    /**
-     * Unsigned comparison belowOrEqual for two numbers.
-     */
-    public static boolean belowOrEqual(int a, int b) {
-        return (a & MASK) <= (b & MASK);
-    }
-
-    /**
-     * Unsigned comparison aboveThan for two numbers.
-     */
-    public static boolean aboveThan(long a, long b) {
-        return (a > b) ^ ((a < 0) != (b < 0));
-    }
-
-    /**
-     * Unsigned comparison aboveOrEqual for two numbers.
-     */
-    public static boolean aboveOrEqual(long a, long b) {
-        return (a >= b) ^ ((a < 0) != (b < 0));
-    }
-
-    /**
-     * Unsigned comparison belowThan for two numbers.
-     */
-    public static boolean belowThan(long a, long b) {
-        return (a < b) ^ ((a < 0) != (b < 0));
-    }
-
-    /**
-     * Unsigned comparison belowOrEqual for two numbers.
-     */
-    public static boolean belowOrEqual(long a, long b) {
-        return (a <= b) ^ ((a < 0) != (b < 0));
-    }
-
-    /**
-     * Unsigned division for two numbers.
-     */
-    public static int divide(int a, int b) {
-        return (int) ((a & MASK) / (b & MASK));
-    }
-
-    /**
-     * Unsigned remainder for two numbers.
-     */
-    public static int remainder(int a, int b) {
-        return (int) ((a & MASK) % (b & MASK));
-    }
-
-    /**
-     * Unsigned division for two numbers.
-     */
-    public static long divide(long a, long b) {
-        return bi(a).divide(bi(b)).longValue();
-    }
-
-    /**
-     * Unsigned remainder for two numbers.
-     */
-    public static long remainder(long a, long b) {
-        return bi(a).remainder(bi(b)).longValue();
-    }
-
-    private static BigInteger bi(long unsigned) {
-        return unsigned >= 0 ? BigInteger.valueOf(unsigned) : BigInteger.valueOf(unsigned & 0x7fffffffffffffffL).setBit(63);
-    }
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,14 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.Value;
 
 /**
  * Utility class for working with the {@link Value} class and its subclasses.
@@ -60,6 +65,11 @@
         return value instanceof JavaConstant;
     }
 
+    public static JavaConstant asConstantJavaValue(JavaValue value) {
+        assert value != null;
+        return (JavaConstant) value;
+    }
+
     public static boolean isAllocatableValue(Value value) {
         assert value != null;
         return value instanceof AllocatableValue;
@@ -80,26 +90,6 @@
         return (StackSlot) value;
     }
 
-    public static boolean isStackSlotValue(Value value) {
-        assert value != null;
-        return value instanceof StackSlotValue;
-    }
-
-    public static StackSlotValue asStackSlotValue(Value value) {
-        assert value != null;
-        return (StackSlotValue) value;
-    }
-
-    public static boolean isVirtualStackSlot(Value value) {
-        assert value != null;
-        return value instanceof VirtualStackSlot;
-    }
-
-    public static VirtualStackSlot asVirtualStackSlot(Value value) {
-        assert value != null;
-        return (VirtualStackSlot) value;
-    }
-
     public static boolean isRegister(Value value) {
         assert value != null;
         return value instanceof RegisterValue;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,15 @@
  */
 package jdk.vm.ci.code;
 
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Set;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * An instance of this class represents an object whose allocation was removed by escape analysis.
@@ -134,45 +140,6 @@
         return id;
     }
 
-    private boolean checkValues() {
-        assert (values == null) == (slotKinds == null);
-        if (values != null) {
-            assert values.length == slotKinds.length;
-            if (!type.isArray()) {
-                ResolvedJavaField[] fields = type.getInstanceFields(true);
-                int fieldIndex = 0;
-                for (int i = 0; i < values.length; i++) {
-                    ResolvedJavaField field = fields[fieldIndex++];
-                    JavaKind valKind = slotKinds[i].getStackKind();
-                    if (field.getJavaKind() == JavaKind.Object) {
-                        assert valKind.isObject() : field + ": " + valKind + " != " + field.getJavaKind();
-                    } else {
-                        if ((valKind == JavaKind.Double || valKind == JavaKind.Long) && field.getJavaKind() == JavaKind.Int) {
-                            assert fields[fieldIndex].getJavaKind() == JavaKind.Int;
-                            fieldIndex++;
-                        } else {
-                            assert valKind == field.getJavaKind().getStackKind() : field + ": " + valKind + " != " + field.getJavaKind();
-                        }
-                    }
-                }
-                assert fields.length == fieldIndex : type + ": fields=" + Arrays.toString(fields) + ", field values=" + Arrays.toString(values);
-            } else {
-                JavaKind componentKind = type.getComponentType().getJavaKind().getStackKind();
-                if (componentKind == JavaKind.Object) {
-                    for (int i = 0; i < values.length; i++) {
-                        assert slotKinds[i].isObject() : slotKinds[i] + " != " + componentKind;
-                    }
-                } else {
-                    for (int i = 0; i < values.length; i++) {
-                        assert slotKinds[i] == componentKind || componentKind.getBitCount() >= slotKinds[i].getBitCount() ||
-                                        (componentKind == JavaKind.Int && slotKinds[i].getBitCount() >= JavaKind.Int.getBitCount()) : slotKinds[i] + " != " + componentKind;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
     /**
      * Overwrites the current set of values with a new one.
      *
@@ -183,7 +150,6 @@
     public void setValues(JavaValue[] values, JavaKind[] slotKinds) {
         this.values = values;
         this.slotKinds = slotKinds;
-        assert checkValues();
     }
 
     @Override
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualStackSlot.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2014, 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 jdk.vm.ci.code;
-
-import jdk.vm.ci.meta.*;
-
-/**
- * {@link VirtualStackSlot}s are stack slots that are not yet fixed to specific frame offset. They
- * are replaced by real {@link StackSlot}s with a fixed position in the frame before code emission.
- */
-public abstract class VirtualStackSlot extends StackSlotValue {
-
-    private final int id;
-
-    public VirtualStackSlot(int id, LIRKind lirKind) {
-        super(lirKind);
-        this.id = id;
-    }
-
-    public int getId() {
-        return id;
-    }
-
-    @Override
-    public String toString() {
-        return "vstack:" + id + getKindSuffix();
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = super.hashCode();
-        result = prime * result + id;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        VirtualStackSlot other = (VirtualStackSlot) obj;
-        if (id != other.id) {
-            return false;
-        }
-        return true;
-    }
-
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java	Wed Jul 05 21:00:20 2017 +0200
@@ -18,10 +18,10 @@
  * if you need additional information or have any questions.
  */
 /**
- * Package that defines the interface between a Java application that wants to install code and the
- * runtime. The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider}
- * interface. The method
- * {@link jdk.vm.ci.code.CodeCacheProvider#addMethod(jdk.vm.ci.meta.ResolvedJavaMethod, CompilationResult, jdk.vm.ci.meta.SpeculationLog, InstalledCode)}
- * can be used to install code for a given method.
+ * Package that defines the interface between a Java application that wants to install code and the runtime.
+ * The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider} interface.
+ * The method {@link jdk.vm.ci.code.CodeCacheProvider#addCode(jdk.vm.ci.meta.ResolvedJavaMethod, CompilationResult, jdk.vm.ci.meta.SpeculationLog, InstalledCode)}
+ * can be used to install code.
  */
 package jdk.vm.ci.code;
+
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.code.stack;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public interface InspectedFrame {
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.code.stack;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public interface StackIntrospection {
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,8 @@
  */
 package jdk.vm.ci.common;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Locale;
 
 /**
  * Indicates a condition in JVMCI related code that should never occur during normal operation.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/Compiler.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.vm.ci.compiler;
-
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.options.*;
-
-public interface Compiler {
-    int INVOCATION_ENTRY_BCI = -1;
-
-    @Option(help = "", type = OptionType.Debug) OptionValue<String> PrintFilter = new OptionValue<>(null);
-    @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
-    @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false);
-    @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
-    @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
-    @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
-    @Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
-
-    /**
-     * Request the compilation of a method by this JVMCI compiler. The compiler should compile the
-     * method to machine code and install it in the code cache if the compilation is successful.
-     *
-     * @param method the method that should be compiled
-     * @param entryBCI the BCI at which to start compiling where -1 denotes a non-OSR compilation
-     *            request and all other values denote an OSR compilation request
-     * @param jvmciEnv pointer to native {@code JVMCIEnv} object
-     * @param id a unique identifier for this compilation
-     */
-    void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id);
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/CompilerFactory.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.vm.ci.compiler;
-
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.runtime.*;
-
-/**
- * Factory for a JVMCI compiler.
- */
-public interface CompilerFactory {
-
-    /**
-     * Get the name of this compiler. The compiler will be selected when the jvmci.compiler system
-     * property is equal to this name.
-     */
-    String getCompilerName();
-
-    /**
-     * Initialize an {@link Architecture}. The compiler has the opportunity to extend the
-     * {@link Architecture} description with a custom subclass.
-     */
-    Architecture initializeArchitecture(Architecture arch);
-
-    /**
-     * Create a new instance of the {@link Compiler}.
-     */
-    Compiler createCompiler(JVMCIRuntime runtime);
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.compiler/src/jdk/vm/ci/compiler/StartupEventListener.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.vm.ci.compiler;
-
-public interface StartupEventListener {
-
-    /**
-     * This method is called before any of the {@link CompilerFactory} methods.
-     */
-    void beforeJVMCIStartup();
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,18 +22,26 @@
  */
 package jdk.vm.ci.hotspot.amd64;
 
-import static jdk.vm.ci.inittimer.InitTimer.*;
+import static jdk.vm.ci.inittimer.InitTimer.timer;
 
-import java.util.*;
+import java.util.EnumSet;
 
-import jdk.vm.ci.amd64.*;
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.compiler.*;
-import jdk.vm.ci.hotspot.*;
-import jdk.vm.ci.inittimer.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.runtime.*;
-import jdk.vm.ci.service.*;
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
+import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
+import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
+import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
+import jdk.vm.ci.hotspot.HotSpotVMConfig;
+import jdk.vm.ci.inittimer.InitTimer;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.runtime.JVMCIBackend;
+import jdk.vm.ci.service.ServiceProvider;
 
 @ServiceProvider(HotSpotJVMCIBackendFactory.class)
 public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
@@ -68,6 +76,9 @@
         if ((config.x86CPUFeatures & config.cpuLZCNT) != 0) {
             features.add(AMD64.CPUFeature.LZCNT);
         }
+        if ((config.x86CPUFeatures & config.cpuERMS) != 0) {
+            features.add(AMD64.CPUFeature.ERMS);
+        }
         if ((config.x86CPUFeatures & config.cpuAVX) != 0) {
             features.add(AMD64.CPUFeature.AVX);
         }
@@ -77,12 +88,42 @@
         if ((config.x86CPUFeatures & config.cpuAES) != 0) {
             features.add(AMD64.CPUFeature.AES);
         }
-        if ((config.x86CPUFeatures & config.cpuERMS) != 0) {
-            features.add(AMD64.CPUFeature.ERMS);
+        if ((config.x86CPUFeatures & config.cpu3DNOWPREFETCH) != 0) {
+            features.add(AMD64.CPUFeature.AMD_3DNOW_PREFETCH);
         }
         if ((config.x86CPUFeatures & config.cpuBMI1) != 0) {
             features.add(AMD64.CPUFeature.BMI1);
         }
+        if ((config.x86CPUFeatures & config.cpuBMI2) != 0) {
+            features.add(AMD64.CPUFeature.BMI2);
+        }
+        if ((config.x86CPUFeatures & config.cpuRTM) != 0) {
+            features.add(AMD64.CPUFeature.RTM);
+        }
+        if ((config.x86CPUFeatures & config.cpuADX) != 0) {
+            features.add(AMD64.CPUFeature.ADX);
+        }
+        if ((config.x86CPUFeatures & config.cpuAVX512F) != 0) {
+            features.add(AMD64.CPUFeature.AVX512F);
+        }
+        if ((config.x86CPUFeatures & config.cpuAVX512DQ) != 0) {
+            features.add(AMD64.CPUFeature.AVX512DQ);
+        }
+        if ((config.x86CPUFeatures & config.cpuAVX512PF) != 0) {
+            features.add(AMD64.CPUFeature.AVX512PF);
+        }
+        if ((config.x86CPUFeatures & config.cpuAVX512ER) != 0) {
+            features.add(AMD64.CPUFeature.AVX512ER);
+        }
+        if ((config.x86CPUFeatures & config.cpuAVX512CD) != 0) {
+            features.add(AMD64.CPUFeature.AVX512CD);
+        }
+        if ((config.x86CPUFeatures & config.cpuAVX512BW) != 0) {
+            features.add(AMD64.CPUFeature.AVX512BW);
+        }
+        if ((config.x86CPUFeatures & config.cpuAVX512VL) != 0) {
+            features.add(AMD64.CPUFeature.AVX512VL);
+        }
         return features;
     }
 
@@ -97,12 +138,12 @@
         return flags;
     }
 
-    protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) {
+    protected TargetDescription createTarget(HotSpotVMConfig config) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = true;
         Architecture arch = new AMD64(computeFeatures(config), computeFlags(config));
-        return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
     protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) {
@@ -132,15 +173,16 @@
     }
 
     @SuppressWarnings("try")
-    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) {
+    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
 
         assert host == null;
-        TargetDescription target = createTarget(runtime.getConfig(), compilerFactory);
+        TargetDescription target = createTarget(runtime.getConfig());
 
         RegisterConfig regConfig;
         HotSpotCodeCacheProvider codeCache;
         ConstantReflectionProvider constantReflection;
         HotSpotMetaAccessProvider metaAccess;
+        StackIntrospection stackIntrospection;
         try (InitTimer t = timer("create providers")) {
             try (InitTimer rt = timer("create MetaAccess provider")) {
                 metaAccess = createMetaAccess(runtime);
@@ -154,13 +196,16 @@
             try (InitTimer rt = timer("create ConstantReflection provider")) {
                 constantReflection = createConstantReflection(runtime);
             }
+            try (InitTimer rt = timer("create StackIntrospection provider")) {
+                stackIntrospection = new HotSpotStackIntrospection(runtime);
+            }
         }
         try (InitTimer rt = timer("instantiate backend")) {
-            return createBackend(metaAccess, codeCache, constantReflection);
+            return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
         }
     }
 
-    protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection) {
-        return new JVMCIBackend(metaAccess, codeCache, constantReflection);
+    protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, StackIntrospection stackIntrospection) {
+        return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,16 +22,47 @@
  */
 package jdk.vm.ci.hotspot.amd64;
 
-import static jdk.vm.ci.amd64.AMD64.*;
-
-import java.util.*;
+import static jdk.vm.ci.amd64.AMD64.r12;
+import static jdk.vm.ci.amd64.AMD64.r15;
+import static jdk.vm.ci.amd64.AMD64.r8;
+import static jdk.vm.ci.amd64.AMD64.r9;
+import static jdk.vm.ci.amd64.AMD64.rax;
+import static jdk.vm.ci.amd64.AMD64.rcx;
+import static jdk.vm.ci.amd64.AMD64.rdi;
+import static jdk.vm.ci.amd64.AMD64.rdx;
+import static jdk.vm.ci.amd64.AMD64.rsi;
+import static jdk.vm.ci.amd64.AMD64.rsp;
+import static jdk.vm.ci.amd64.AMD64.xmm0;
+import static jdk.vm.ci.amd64.AMD64.xmm1;
+import static jdk.vm.ci.amd64.AMD64.xmm2;
+import static jdk.vm.ci.amd64.AMD64.xmm3;
+import static jdk.vm.ci.amd64.AMD64.xmm4;
+import static jdk.vm.ci.amd64.AMD64.xmm5;
+import static jdk.vm.ci.amd64.AMD64.xmm6;
+import static jdk.vm.ci.amd64.AMD64.xmm7;
 
-import jdk.vm.ci.amd64.*;
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.code.CallingConvention.*;
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.hotspot.*;
-import jdk.vm.ci.meta.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.CallingConvention.Type;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterAttributes;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotVMConfig;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.Value;
 
 public class AMD64HotSpotRegisterConfig implements RegisterConfig {
 
@@ -86,28 +117,30 @@
      */
     private final boolean needsNativeStackHomeSpace;
 
-    private static Register[] initAllocatable(boolean reserveForHeapBase) {
-        Register[] registers = null;
-        // @formatter:off
-        if (reserveForHeapBase) {
-            registers = new Register[] {
-                        rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, /*r12,*/ r13, r14, /*r15, */
-                        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
-                        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
-                      };
-        } else {
-            registers = new Register[] {
-                        rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9,  r10, r11, r12, r13, r14, /*r15, */
-                        xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
-                        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
-                      };
+    private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        Register[] allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 3 : 2)];
+
+        int idx = 0;
+        for (Register reg : allRegisters) {
+            if (reg.equals(rsp) || reg.equals(r15)) {
+                // skip stack pointer and thread register
+                continue;
+            }
+            if (reserveForHeapBase && reg.equals(r12)) {
+                // skip heap base register
+                continue;
+            }
+
+            registers[idx++] = reg;
         }
-       // @formatter:on
+
+        assert idx == registers.length;
         return registers;
     }
 
     public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
-        this(architecture, config, initAllocatable(config.useCompressedOops));
+        this(architecture, config, initAllocatable(architecture, config.useCompressedOops));
         assert callerSaved.length >= allocatable.length;
     }
 
@@ -125,7 +158,7 @@
             this.needsNativeStackHomeSpace = false;
         }
 
-        this.allocatable = allocatable.clone();
+        this.allocatable = allocatable;
         Set<Register> callerSaveSet = new HashSet<>();
         Collections.addAll(callerSaveSet, allocatable);
         Collections.addAll(callerSaveSet, xmmParameterRegisters);
@@ -134,7 +167,7 @@
         callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
 
         allAllocatableAreCallerSaved = true;
-        attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
+        attributesMap = RegisterAttributes.createMap(this, architecture.getRegisters());
     }
 
     @Override
@@ -221,7 +254,7 @@
             if (locations[i] == null) {
                 LIRKind lirKind = target.getLIRKind(kind);
                 locations[i] = StackSlot.get(lirKind, currentStackOffset, !type.out);
-                currentStackOffset += Math.max(target.getSizeInBytes(lirKind.getPlatformKind()), target.wordSize);
+                currentStackOffset += Math.max(lirKind.getPlatformKind().getSizeInBytes(), target.wordSize);
             }
         }
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,28 +22,36 @@
  */
 package jdk.vm.ci.hotspot.sparc;
 
-import static jdk.vm.ci.inittimer.InitTimer.*;
+import static jdk.vm.ci.inittimer.InitTimer.timer;
 
-import java.util.*;
+import java.util.EnumSet;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.compiler.*;
-import jdk.vm.ci.hotspot.*;
-import jdk.vm.ci.inittimer.*;
-import jdk.vm.ci.runtime.*;
-import jdk.vm.ci.service.*;
-import jdk.vm.ci.sparc.*;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
+import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
+import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
+import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
+import jdk.vm.ci.hotspot.HotSpotVMConfig;
+import jdk.vm.ci.inittimer.InitTimer;
+import jdk.vm.ci.runtime.JVMCIBackend;
+import jdk.vm.ci.service.ServiceProvider;
+import jdk.vm.ci.sparc.SPARC;
 import jdk.vm.ci.sparc.SPARC.CPUFeature;
 
 @ServiceProvider(HotSpotJVMCIBackendFactory.class)
 public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
 
-    protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) {
+    protected TargetDescription createTarget(HotSpotVMConfig config) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = false;
         Architecture arch = new SPARC(computeFeatures(config));
-        return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
+        return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
     protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
@@ -64,8 +72,62 @@
         if ((config.sparcFeatures & config.cbcondInstructions) != 0) {
             features.add(CPUFeature.CBCOND);
         }
-        if (config.useBlockZeroing) {
-            features.add(CPUFeature.BLOCK_ZEROING);
+        if ((config.sparcFeatures & config.v8Instructions) != 0) {
+            features.add(CPUFeature.V8);
+        }
+        if ((config.sparcFeatures & config.hardwareMul32) != 0) {
+            features.add(CPUFeature.HARDWARE_MUL32);
+        }
+        if ((config.sparcFeatures & config.hardwareDiv32) != 0) {
+            features.add(CPUFeature.HARDWARE_DIV32);
+        }
+        if ((config.sparcFeatures & config.hardwareFsmuld) != 0) {
+            features.add(CPUFeature.HARDWARE_FSMULD);
+        }
+        if ((config.sparcFeatures & config.hardwarePopc) != 0) {
+            features.add(CPUFeature.HARDWARE_POPC);
+        }
+        if ((config.sparcFeatures & config.v9Instructions) != 0) {
+            features.add(CPUFeature.V9);
+        }
+        if ((config.sparcFeatures & config.sun4v) != 0) {
+            features.add(CPUFeature.SUN4V);
+        }
+        if ((config.sparcFeatures & config.blkInitInstructions) != 0) {
+            features.add(CPUFeature.BLK_INIT_INSTRUCTIONS);
+        }
+        if ((config.sparcFeatures & config.fmafInstructions) != 0) {
+            features.add(CPUFeature.FMAF);
+        }
+        if ((config.sparcFeatures & config.fmauInstructions) != 0) {
+            features.add(CPUFeature.FMAU);
+        }
+        if ((config.sparcFeatures & config.sparc64Family) != 0) {
+            features.add(CPUFeature.SPARC64_FAMILY);
+        }
+        if ((config.sparcFeatures & config.mFamily) != 0) {
+            features.add(CPUFeature.M_FAMILY);
+        }
+        if ((config.sparcFeatures & config.tFamily) != 0) {
+            features.add(CPUFeature.T_FAMILY);
+        }
+        if ((config.sparcFeatures & config.t1Model) != 0) {
+            features.add(CPUFeature.T1_MODEL);
+        }
+        if ((config.sparcFeatures & config.sparc5Instructions) != 0) {
+            features.add(CPUFeature.SPARC5);
+        }
+        if ((config.sparcFeatures & config.aesInstructions) != 0) {
+            features.add(CPUFeature.SPARC64_FAMILY);
+        }
+        if ((config.sparcFeatures & config.sha1Instruction) != 0) {
+            features.add(CPUFeature.SHA1);
+        }
+        if ((config.sparcFeatures & config.sha256Instruction) != 0) {
+            features.add(CPUFeature.SHA256);
+        }
+        if ((config.sparcFeatures & config.sha512Instruction) != 0) {
+            features.add(CPUFeature.SHA512);
         }
         return features;
     }
@@ -81,20 +143,22 @@
     }
 
     @SuppressWarnings("try")
-    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) {
+    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
         assert host == null;
-        TargetDescription target = createTarget(runtime.getConfig(), compilerFactory);
+        TargetDescription target = createTarget(runtime.getConfig());
 
         HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
-        RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target, runtime.getConfig());
+        RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target.arch, runtime.getConfig());
         HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target, regConfig);
         HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
+        StackIntrospection stackIntrospection = new HotSpotStackIntrospection(runtime);
         try (InitTimer rt = timer("instantiate backend")) {
-            return createBackend(metaAccess, codeCache, constantReflection);
+            return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
         }
     }
 
-    protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection) {
-        return new JVMCIBackend(metaAccess, codeCache, constantReflection);
+    protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection,
+                    StackIntrospection stackIntrospection) {
+        return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,16 +22,72 @@
  */
 package jdk.vm.ci.hotspot.sparc;
 
-import static jdk.vm.ci.sparc.SPARC.*;
-
-import java.util.*;
+import static jdk.vm.ci.code.CallingConvention.Type.JavaCall;
+import static jdk.vm.ci.code.CallingConvention.Type.JavaCallee;
+import static jdk.vm.ci.code.CallingConvention.Type.NativeCall;
+import static jdk.vm.ci.meta.JavaKind.Void;
+import static jdk.vm.ci.meta.Value.ILLEGAL;
+import static jdk.vm.ci.sparc.SPARC.REGISTER_SAFE_AREA_SIZE;
+import static jdk.vm.ci.sparc.SPARC.d0;
+import static jdk.vm.ci.sparc.SPARC.d2;
+import static jdk.vm.ci.sparc.SPARC.d4;
+import static jdk.vm.ci.sparc.SPARC.d6;
+import static jdk.vm.ci.sparc.SPARC.f0;
+import static jdk.vm.ci.sparc.SPARC.f1;
+import static jdk.vm.ci.sparc.SPARC.f2;
+import static jdk.vm.ci.sparc.SPARC.f3;
+import static jdk.vm.ci.sparc.SPARC.f4;
+import static jdk.vm.ci.sparc.SPARC.f5;
+import static jdk.vm.ci.sparc.SPARC.f6;
+import static jdk.vm.ci.sparc.SPARC.f7;
+import static jdk.vm.ci.sparc.SPARC.g0;
+import static jdk.vm.ci.sparc.SPARC.g2;
+import static jdk.vm.ci.sparc.SPARC.g6;
+import static jdk.vm.ci.sparc.SPARC.i0;
+import static jdk.vm.ci.sparc.SPARC.i1;
+import static jdk.vm.ci.sparc.SPARC.i2;
+import static jdk.vm.ci.sparc.SPARC.i3;
+import static jdk.vm.ci.sparc.SPARC.i4;
+import static jdk.vm.ci.sparc.SPARC.i5;
+import static jdk.vm.ci.sparc.SPARC.i6;
+import static jdk.vm.ci.sparc.SPARC.i7;
+import static jdk.vm.ci.sparc.SPARC.l0;
+import static jdk.vm.ci.sparc.SPARC.l1;
+import static jdk.vm.ci.sparc.SPARC.l2;
+import static jdk.vm.ci.sparc.SPARC.l3;
+import static jdk.vm.ci.sparc.SPARC.l4;
+import static jdk.vm.ci.sparc.SPARC.l5;
+import static jdk.vm.ci.sparc.SPARC.l6;
+import static jdk.vm.ci.sparc.SPARC.l7;
+import static jdk.vm.ci.sparc.SPARC.o0;
+import static jdk.vm.ci.sparc.SPARC.o1;
+import static jdk.vm.ci.sparc.SPARC.o2;
+import static jdk.vm.ci.sparc.SPARC.o3;
+import static jdk.vm.ci.sparc.SPARC.o4;
+import static jdk.vm.ci.sparc.SPARC.o5;
+import static jdk.vm.ci.sparc.SPARC.sp;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.code.CallingConvention.*;
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.hotspot.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.sparc.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.CallingConvention.Type;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterAttributes;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotVMConfig;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.sparc.SPARC;
 
 public class SPARCHotSpotRegisterConfig implements RegisterConfig {
 
@@ -41,6 +97,11 @@
 
     private final RegisterAttributes[] attributesMap;
 
+    /**
+     * Does native code (C++ code) spill arguments in registers to the parent frame?
+     */
+    private final boolean addNativeRegisterArgumentSlots;
+
     @Override
     public Register[] getAllocatableRegisters() {
         return allocatable.clone();
@@ -50,22 +111,9 @@
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : registers) {
             if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
-                // Special treatment for double precision
-                // TODO: This is wasteful it uses only half of the registers as float.
-                if (kind == JavaKind.Double) {
-                    if (reg.getRegisterCategory().equals(FPUd)) {
-                        list.add(reg);
-                    }
-                } else if (kind == JavaKind.Float) {
-                    if (reg.getRegisterCategory().equals(FPUs)) {
-                        list.add(reg);
-                    }
-                } else {
-                    list.add(reg);
-                }
+                list.add(reg);
             }
         }
-
         Register[] ret = list.toArray(new Register[list.size()]);
         return ret;
     }
@@ -78,76 +126,57 @@
     private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
     private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
 
-    private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
+    private final Register[] fpuFloatParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
     private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
+
     // @formatter:off
-    private final Register[] callerSaveRegisters =
-                   {g1, g2, g3, g4, g5, g6, g7,
-                    o0, o1, o2, o3, o4, o5, o7,
-                    f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
-                    f8,  f9,  f10, f11, f12, f13, f14, f15,
-                    f16, f17, f18, f19, f20, f21, f22, f23,
-                    f24, f25, f26, f27, f28, f29, f30, f31,
-                    d32, d34, d36, d38, d40, d42, d44, d46,
-                    d48, d50, d52, d54, d56, d58, d60, d62};
-    // @formatter:on
+    private final Register[] callerSaveRegisters;
 
     /**
      * Registers saved by the callee. This lists all L and I registers which are saved in the
      * register window.
      */
-    private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, i6, i7};
+    private final Register[] calleeSaveRegisters = {
+                    l0, l1, l2, l3, l4, l5, l6, l7,
+                    i0, i1, i2, i3, i4, i5, i6, i7};
+    // @formatter:on
+
+    private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        Register[] allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 4 : 3)];
 
-    private static Register[] initAllocatable(boolean reserveForHeapBase) {
-        Register[] registers = null;
-        if (reserveForHeapBase) {
-            // @formatter:off
-            registers = new Register[]{
-                        // TODO this is not complete
-                        // o7 cannot be used as register because it is always overwritten on call
-                        // and the current register handler would ignore this fact if the called
-                        // method still does not modify registers, in fact o7 is modified by the Call instruction
-                        // There would be some extra handlin necessary to be able to handle the o7 properly for local usage
-                        g1, g4, g5,
-                        o0, o1, o2, o3, o4, o5, /*o6,o7,*/
-                        l0, l1, l2, l3, l4, l5, l6, l7,
-                        i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
-                        //f0, f1, f2, f3, f4, f5, f6, f7,
-                        f8,  f9,  f10, f11, f12, f13, f14, f15,
-                        f16, f17, f18, f19, f20, f21, f22, f23,
-                        f24, f25, f26, f27, f28, f29, f30, f31,
-                        d32, d34, d36, d38, d40, d42, d44, d46,
-                        d48, d50, d52, d54, d56, d58, d60, d62
-            };
-            // @formatter:on
-        } else {
-            // @formatter:off
-            registers = new Register[]{
-                        // TODO this is not complete
-                        g1, g4, g5,
-                        o0, o1, o2, o3, o4, o5, /*o6, o7,*/
-                        l0, l1, l2, l3, l4, l5, l6, l7,
-                        i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
-//                        f0, f1, f2, f3, f4, f5, f6, f7
-                        f8,  f9,  f10, f11, f12, f13, f14, f15,
-                        f16, f17, f18, f19, f20, f21, f22, f23,
-                        f24, f25, f26, f27, f28, f29, f30, f31,
-                        d32, d34, d36, d38, d40, d42, d44, d46,
-                        d48, d50, d52, d54, d56, d58, d60, d62
-            };
-            // @formatter:on
+        int idx = 0;
+        for (Register reg : allRegisters) {
+            if (reg.equals(sp) || reg.equals(g2) || reg.equals(g0)) {
+                // skip g0, stack pointer and thread register
+                continue;
+            }
+            if (reserveForHeapBase && reg.equals(g6)) {
+                // skip heap base register
+                continue;
+            }
+
+            registers[idx++] = reg;
         }
 
+        assert idx == registers.length;
         return registers;
     }
 
-    public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
-        this(target, initAllocatable(config.useCompressedOops));
+    public SPARCHotSpotRegisterConfig(Architecture arch, HotSpotVMConfig config) {
+        this(arch, initAllocatable(arch, config.useCompressedOops), config);
     }
 
-    public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
-        this.architecture = target.arch;
+    public SPARCHotSpotRegisterConfig(Architecture arch, Register[] allocatable, HotSpotVMConfig config) {
+        this.architecture = arch;
         this.allocatable = allocatable.clone();
+        this.addNativeRegisterArgumentSlots = config.linuxOs;
+        HashSet<Register> callerSaveSet = new HashSet<>();
+        Collections.addAll(callerSaveSet, arch.getAvailableValueRegisters());
+        for (Register cs : calleeSaveRegisters) {
+            callerSaveSet.remove(cs);
+        }
+        this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
         attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
     }
 
@@ -172,21 +201,31 @@
 
     @Override
     public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
-        if (type == Type.JavaCall || type == Type.NativeCall) {
+        if (type == JavaCall || type == NativeCall) {
             return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
         }
-        if (type == Type.JavaCallee) {
+        if (type == JavaCallee) {
             return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
         }
         throw JVMCIError.shouldNotReachHere();
     }
 
     public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
-        if (architecture.canStoreValue(FPUs, kind) || architecture.canStoreValue(FPUd, kind)) {
-            return fpuParameterRegisters;
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Short:
+            case Char:
+            case Int:
+            case Long:
+            case Object:
+                return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
+            case Double:
+            case Float:
+                return fpuFloatParameterRegisters;
+            default:
+                throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind);
         }
-        assert architecture.canStoreValue(CPU, kind);
-        return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
     }
 
     private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
@@ -213,7 +252,7 @@
                     }
                     break;
                 case Double:
-                    if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
+                    if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) {
                         if (currentFloating % 2 != 0) {
                             // Make register number even to be a double reg
                             currentFloating++;
@@ -224,8 +263,8 @@
                     }
                     break;
                 case Float:
-                    if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
-                        Register register = fpuParameterRegisters[currentFloating++];
+                    if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) {
+                        Register register = fpuFloatParameterRegisters[currentFloating++];
                         locations[i] = register.asValue(target.getLIRKind(kind));
                     }
                     break;
@@ -234,20 +273,27 @@
             }
 
             if (locations[i] == null) {
+                LIRKind lirKind = target.getLIRKind(kind);
                 // Stack slot is always aligned to its size in bytes but minimum wordsize
-                int typeSize = SPARC.spillSlotSize(target, kind);
+                int typeSize = lirKind.getPlatformKind().getSizeInBytes();
                 currentStackOffset = roundUp(currentStackOffset, typeSize);
-                int slotOffset = currentStackOffset + SPARC.REGISTER_SAFE_AREA_SIZE;
-                locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), slotOffset, !type.out);
+                int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE;
+                locations[i] = StackSlot.get(lirKind, slotOffset, !type.out);
                 currentStackOffset += typeSize;
             }
         }
 
-        JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
-        AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind()));
-        // Space where callee may spill outgoing parameters o0...o5
-        int lowerOutgoingSpace = Math.min(locations.length, 6) * target.wordSize;
-        return new CallingConvention(currentStackOffset + lowerOutgoingSpace, returnLocation, locations);
+        JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind();
+        AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind()));
+
+        int outArgSpillArea;
+        if (type == NativeCall && addNativeRegisterArgumentSlots) {
+            // Space for native callee which may spill our outgoing arguments
+            outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize;
+        } else {
+            outArgSpillArea = 0;
+        }
+        return new CallingConvention(currentStackOffset + outArgSpillArea, returnLocation, locations);
     }
 
     private static int roundUp(int number, int mod) {
@@ -256,7 +302,7 @@
 
     @Override
     public Register getReturnRegister(JavaKind kind) {
-        return getReturnRegister(kind, Type.JavaCallee);
+        return getReturnRegister(kind, JavaCallee);
     }
 
     private static Register getReturnRegister(JavaKind kind, Type type) {
@@ -268,7 +314,7 @@
             case Int:
             case Long:
             case Object:
-                return type == Type.JavaCallee ? i0 : o0;
+                return type == JavaCallee ? i0 : o0;
             case Float:
                 return f0;
             case Double:
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
 
 package jdk.vm.ci.hotspot;
 
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.inittimer.InitTimer.timer;
 
 import java.lang.reflect.Constructor;
@@ -36,7 +37,6 @@
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.vm.ci.meta.SpeculationLog;
 import sun.misc.Unsafe;
 
 /**
@@ -44,7 +44,7 @@
  * pointer as an argument (e.g., {@link #getSymbol(long)}) is undefined if the argument does not
  * denote a valid native object.
  */
-public final class CompilerToVM {
+final class CompilerToVM {
     /**
      * Initializes the native part of the JVMCI runtime.
      */
@@ -62,6 +62,14 @@
     }
 
     /**
+     * Gets the {@link CompilerToVM} instance associated with the singleton
+     * {@link HotSpotJVMCIRuntime} instance.
+     */
+    public static CompilerToVM compilerToVM() {
+        return runtime().getCompilerToVM();
+    }
+
+    /**
      * Copies the original bytecode of {@code method} into a new byte array and returns it.
      *
      * @return a new byte array containing the original bytecode of {@code method}
@@ -301,7 +309,7 @@
      *         {@link HotSpotVMConfig#codeInstallResultDependenciesFailed} or
      *         {@link HotSpotVMConfig#codeInstallResultDependenciesInvalid}.
      */
-    public native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog);
+    native int installCode(TargetDescription target, HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog);
 
     public native int getMetadata(TargetDescription target, HotSpotCompiledCode compiledCode, HotSpotMetaData metaData);
 
@@ -317,18 +325,18 @@
      * @param timeUnitsPerSecond the granularity of the units for the {@code time} value
      * @param installedCode the nmethod installed as a result of the compilation
      */
-    public synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethodImpl method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond,
+    synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethodImpl method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond,
                     InstalledCode installedCode);
 
     /**
      * Resets all compilation statistics.
      */
-    public native void resetCompilationStatistics();
+    native void resetCompilationStatistics();
 
     /**
      * Initializes the fields of {@code config}.
      */
-    native long initializeConfiguration();
+    native long initializeConfiguration(HotSpotVMConfig config);
 
     /**
      * Resolves the implementation of {@code method} for virtual dispatches on objects of dynamic
@@ -367,7 +375,7 @@
      * @param address an address that may be called from any code in the code cache
      * @return -1 if {@code address == 0}
      */
-    public native long getMaxCallTargetOffset(long address);
+    native long getMaxCallTargetOffset(long address);
 
     /**
      * Gets a textual disassembly of {@code codeBlob}.
@@ -376,7 +384,7 @@
      *         {@code codeBlob} could not be disassembled for some reason
      */
     // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage
-    public synchronized native String disassembleCodeBlob(long codeBlob);
+    synchronized native String disassembleCodeBlob(InstalledCode installedCode);
 
     /**
      * Gets a stack trace element for {@code method} at bytecode index {@code bci}.
@@ -454,12 +462,12 @@
      * Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be
      * raised the next time {@code installedCode} is executed.
      */
-    public native void invalidateInstalledCode(InstalledCode installedCode);
+    native void invalidateInstalledCode(InstalledCode installedCode);
 
     /**
      * Collects the current values of all JVMCI benchmark counters, summed up over all threads.
      */
-    public native long[] collectCounters();
+    native long[] collectCounters();
 
     /**
      * Determines if {@code metaspaceMethodData} is mature.
@@ -489,7 +497,7 @@
      * @param methods the methods to look for, where {@code null} means that any frame is returned
      * @return the frame, or {@code null} if the end of the stack was reached during the search
      */
-    public native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, HotSpotResolvedJavaMethodImpl[] methods, int initialSkip);
+    native HotSpotStackFrameReference getNextStackFrame(HotSpotStackFrameReference frame, ResolvedJavaMethod[] methods, int initialSkip);
 
     /**
      * Materializes all virtual objects within {@code stackFrame} updates its locals.
@@ -512,30 +520,34 @@
     /**
      * Determines if debug info should also be emitted at non-safepoint locations.
      */
-    public native boolean shouldDebugNonSafepoints();
+
+    native boolean shouldDebugNonSafepoints();
 
     /**
      * Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to the
      * HotSpot's log stream.
      *
-     * @exception NullPointerException if <code>bytes</code> is <code>null</code>.
+     * @exception NullPointerException if {@code bytes == null}
      * @exception IndexOutOfBoundsException if copying would cause access of data outside array
-     *                bounds.
+     *                bounds
      */
-    public native void writeDebugOutput(byte[] bytes, int offset, int length);
+    native void writeDebugOutput(byte[] bytes, int offset, int length);
 
     /**
      * Flush HotSpot's log stream.
      */
-    public native void flushDebugOutput();
+    native void flushDebugOutput();
 
     /**
-     * Read a value representing a metaspace Method* and return the
-     * {@link HotSpotResolvedJavaMethodImpl} wrapping it. This method does no checking that the
-     * location actually contains a valid Method*. If the {@code base} object is a
+     * Read a HotSpot Method* value from the memory location described by {@code base} plus
+     * {@code displacement} and return the {@link HotSpotResolvedJavaMethodImpl} wrapping it. This
+     * method does no checking that the memory location actually contains a valid pointer and may
+     * crash the VM if an invalid location is provided. If the {@code base} is null then
+     * {@code displacement} is used by itself. If {@code base} is a
      * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
      * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
-     * and used as the base. Otherwise the object itself is used as the base.
+     * and added to {@code displacement}. Any other non-null object type causes an
+     * {@link IllegalArgumentException} to be thrown.
      *
      * @param base an object to read from or null
      * @param displacement
@@ -544,12 +556,14 @@
     native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, long displacement);
 
     /**
-     * Read a value representing a metaspace ConstantPool* and return the
-     * {@link HotSpotConstantPool} wrapping it. This method does no checking that the location
-     * actually contains a valid ConstantPool*. If the {@code base} object is a
-     * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
-     * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
-     * and used as the base. Otherwise the object itself is used as the base.
+     * Read a HotSpot ConstantPool* value from the memory location described by {@code base} plus
+     * {@code displacement} and return the {@link HotSpotConstantPool} wrapping it. This method does
+     * no checking that the memory location actually contains a valid pointer and may crash the VM
+     * if an invalid location is provided. If the {@code base} is null then {@code displacement} is
+     * used by itself. If {@code base} is a {@link HotSpotResolvedJavaMethodImpl},
+     * {@link HotSpotConstantPool} or {@link HotSpotResolvedObjectTypeImpl} then the metaspace
+     * pointer is fetched from that object and added to {@code displacement}. Any other non-null
+     * object type causes an {@link IllegalArgumentException} to be thrown.
      *
      * @param base an object to read from or null
      * @param displacement
@@ -558,12 +572,15 @@
     native HotSpotConstantPool getConstantPool(Object base, long displacement);
 
     /**
-     * Read a value representing a metaspace Klass* and return the
-     * {@link HotSpotResolvedObjectTypeImpl} wrapping it. The method does no checking that the
-     * location actually contains a valid Klass*. If the {@code base} object is a
+     * Read a HotSpot Klass* value from the memory location described by {@code base} plus
+     * {@code displacement} and return the {@link HotSpotResolvedObjectTypeImpl} wrapping it. This
+     * method does no checking that the memory location actually contains a valid pointer and may
+     * crash the VM if an invalid location is provided. If the {@code base} is null then
+     * {@code displacement} is used by itself. If {@code base} is a
      * {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
      * {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
-     * and used as the base. Otherwise the object itself is used as the base.
+     * and added to {@code displacement}. Any other non-null object type causes an
+     * {@link IllegalArgumentException} to be thrown.
      *
      * @param base an object to read from or null
      * @param displacement
@@ -571,4 +588,17 @@
      * @return null or the resolved method for this location
      */
     native HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement, boolean compressed);
+
+    /**
+     * Return the size of the HotSpot ProfileData* pointed at by {@code position}. If
+     * {@code position} is outside the space of the MethodData then an
+     * {@link IllegalArgumentException} is thrown. A {@code position} inside the MethodData but that
+     * isn't pointing at a valid ProfileData will crash the VM.
+     *
+     * @param metaspaceMethodData
+     * @param position
+     * @return the size of the ProfileData item pointed at by {@code position}
+     * @throws IllegalArgumentException if an out of range position is given
+     */
+    native int methodDataProfileDataSize(long metaspaceMethodData, int position);
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,15 +22,30 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotCompressedNullConstant.*;
+import static jdk.vm.ci.hotspot.HotSpotCompressedNullConstant.COMPRESSED_NULL;
 
-import java.lang.reflect.*;
+import java.lang.reflect.Field;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.code.CompilationResult.*;
-import jdk.vm.ci.code.DataSection.*;
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.BailoutException;
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.CompilationRequest;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.CompilationResult.Call;
+import jdk.vm.ci.code.CompilationResult.ConstantReference;
+import jdk.vm.ci.code.CompilationResult.DataPatch;
+import jdk.vm.ci.code.CompilationResult.Mark;
+import jdk.vm.ci.code.DataSection;
+import jdk.vm.ci.code.DataSection.Data;
+import jdk.vm.ci.code.DataSection.DataBuilder;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.SerializableConstant;
+import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.VMConstant;
 
 /**
  * HotSpot implementation of {@link CodeCacheProvider}.
@@ -98,72 +113,64 @@
         return runtime.getConfig().runtimeCallStackSize;
     }
 
-    public InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
-        HotSpotJVMCIRuntime.runtime().notifyInstall(this, installedCode, compResult);
+    private InstalledCode logOrDump(InstalledCode installedCode, CompilationResult compResult) {
+        ((HotSpotJVMCIRuntime) runtime).notifyInstall(this, installedCode, compResult);
         return installedCode;
     }
 
-    private InstalledCode installCode(CompilationResult compResult, HotSpotCompiledNmethod compiledCode, InstalledCode installedCode, SpeculationLog log) {
-        int result = runtime.getCompilerToVM().installCode(target, compiledCode, installedCode, log);
-        if (result != config.codeInstallResultOk) {
-            String msg = compiledCode.getInstallationFailureMessage();
-            String resultDesc = config.getCodeInstallResultDescription(result);
-            if (msg != null) {
-                msg = String.format("Code installation failed: %s%n%s", resultDesc, msg);
+    public InstalledCode installCode(CompilationRequest compRequest, CompilationResult compResult, InstalledCode installedCode, SpeculationLog log, boolean isDefault) {
+        HotSpotResolvedJavaMethod method = compRequest != null ? (HotSpotResolvedJavaMethod) compRequest.getMethod() : null;
+        InstalledCode resultInstalledCode;
+        if (installedCode == null) {
+            if (method == null) {
+                // Must be a stub
+                resultInstalledCode = new HotSpotRuntimeStub(compResult.getName());
             } else {
-                msg = String.format("Code installation failed: %s", resultDesc);
+                resultInstalledCode = new HotSpotNmethod(method, compResult.getName(), isDefault);
             }
-            if (result == config.codeInstallResultDependenciesInvalid) {
-                throw new AssertionError(resultDesc + " " + msg);
+        } else {
+            resultInstalledCode = installedCode;
+        }
+        HotSpotCompiledCode compiledCode;
+        if (method != null) {
+            final int id;
+            final long jvmciEnv;
+            if (compRequest instanceof HotSpotCompilationRequest) {
+                HotSpotCompilationRequest hsCompRequest = (HotSpotCompilationRequest) compRequest;
+                id = hsCompRequest.getId();
+                jvmciEnv = hsCompRequest.getJvmciEnv();
+            } else {
+                id = method.allocateCompileId(compRequest.getEntryBCI());
+                jvmciEnv = 0L;
             }
-            throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg);
+            compiledCode = new HotSpotCompiledNmethod(method, compResult, id, jvmciEnv);
+        } else {
+            compiledCode = new HotSpotCompiledCode(compResult);
         }
-        return logOrDump(installedCode, compResult);
-    }
-
-    public InstalledCode installMethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv, boolean isDefault) {
-        if (compResult.getId() == -1) {
-            compResult.setId(method.allocateCompileId(compResult.getEntryBCI()));
+        int result = runtime.getCompilerToVM().installCode(target, compiledCode, resultInstalledCode, (HotSpotSpeculationLog) log);
+        if (result != config.codeInstallResultOk) {
+            String resultDesc = config.getCodeInstallResultDescription(result);
+            if (compiledCode instanceof HotSpotCompiledNmethod) {
+                HotSpotCompiledNmethod compiledNmethod = (HotSpotCompiledNmethod) compiledCode;
+                String msg = compiledNmethod.getInstallationFailureMessage();
+                if (msg != null) {
+                    msg = String.format("Code installation failed: %s%n%s", resultDesc, msg);
+                } else {
+                    msg = String.format("Code installation failed: %s", resultDesc);
+                }
+                if (result == config.codeInstallResultDependenciesInvalid) {
+                    throw new AssertionError(resultDesc + " " + msg);
+                }
+                throw new BailoutException(result != config.codeInstallResultDependenciesFailed, msg);
+            } else {
+                throw new BailoutException("Error installing %s: %s", compResult.getName(), resultDesc);
+            }
         }
-        HotSpotInstalledCode installedCode = new HotSpotNmethod(method, compResult.getName(), isDefault);
-        HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(method, compResult, jvmciEnv);
-        return installCode(compResult, compiledCode, installedCode, method.getSpeculationLog());
+        return logOrDump(resultInstalledCode, compResult);
     }
 
-    @Override
-    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode predefinedInstalledCode) {
-        HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
-        if (compResult.getId() == -1) {
-            compResult.setId(hotspotMethod.allocateCompileId(compResult.getEntryBCI()));
-        }
-        InstalledCode installedCode = predefinedInstalledCode;
-        if (installedCode == null) {
-            HotSpotInstalledCode code = new HotSpotNmethod(hotspotMethod, compResult.getName(), false);
-            installedCode = code;
-        }
-        HotSpotCompiledNmethod compiledCode = new HotSpotCompiledNmethod(hotspotMethod, compResult);
-        return installCode(compResult, compiledCode, installedCode, log);
-    }
-
-    @Override
-    public InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult) {
-        HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method;
-        return installMethod(hotspotMethod, compResult, 0L, true);
-    }
-
-    public HotSpotNmethod addExternalMethod(ResolvedJavaMethod method, CompilationResult compResult) {
-        HotSpotResolvedJavaMethod javaMethod = (HotSpotResolvedJavaMethod) method;
-        if (compResult.getId() == -1) {
-            compResult.setId(javaMethod.allocateCompileId(compResult.getEntryBCI()));
-        }
-        HotSpotNmethod code = new HotSpotNmethod(javaMethod, compResult.getName(), false, true);
-        HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(javaMethod, compResult);
-        CompilerToVM vm = runtime.getCompilerToVM();
-        int result = vm.installCode(target, compiled, code, null);
-        if (result != runtime.getConfig().codeInstallResultOk) {
-            return null;
-        }
-        return code;
+    public void invalidateInstalledCode(InstalledCode installedCode) {
+        runtime.getCompilerToVM().invalidateInstalledCode(installedCode);
     }
 
     public boolean needsDataPatch(JavaConstant constant) {
@@ -176,35 +183,29 @@
         if (constant instanceof VMConstant) {
             VMConstant vmConstant = (VMConstant) constant;
             boolean compressed;
-            long raw;
-            if (constant instanceof HotSpotObjectConstant) {
-                HotSpotObjectConstant c = (HotSpotObjectConstant) vmConstant;
+            if (constant instanceof HotSpotConstant) {
+                HotSpotConstant c = (HotSpotConstant) vmConstant;
                 compressed = c.isCompressed();
-                raw = 0xDEADDEADDEADDEADL;
-            } else if (constant instanceof HotSpotMetaspaceConstant) {
-                HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) constant;
-                compressed = meta.isCompressed();
-                raw = meta.rawValue();
             } else {
                 throw new JVMCIError(String.valueOf(constant));
             }
 
-            size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind);
+            size = compressed ? 4 : target.wordSize;
             if (size == 4) {
                 builder = (buffer, patch) -> {
                     patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
-                    buffer.putInt((int) raw);
+                    buffer.putInt(0xDEADDEAD);
                 };
             } else {
                 assert size == 8;
                 builder = (buffer, patch) -> {
                     patch.accept(new DataPatch(buffer.position(), new ConstantReference(vmConstant)));
-                    buffer.putLong(raw);
+                    buffer.putLong(0xDEADDEADDEADDEADL);
                 };
             }
         } else if (JavaConstant.isNull(constant)) {
             boolean compressed = COMPRESSED_NULL.equals(constant);
-            size = target.getSizeInBytes(compressed ? JavaKind.Int : target.wordKind);
+            size = compressed ? 4 : target.wordSize;
             builder = DataBuilder.zero(size);
         } else if (constant instanceof SerializableConstant) {
             SerializableConstant s = (SerializableConstant) constant;
@@ -250,8 +251,7 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long codeBlob = code.getAddress();
-            return runtime.getCompilerToVM().disassembleCodeBlob(codeBlob);
+            return runtime.getCompilerToVM().disassembleCodeBlob(code);
         }
         return null;
     }
@@ -259,4 +259,35 @@
     public SpeculationLog createSpeculationLog() {
         return new HotSpotSpeculationLog();
     }
+
+    public long getMaxCallTargetOffset(long address) {
+        return runtime.getCompilerToVM().getMaxCallTargetOffset(address);
+    }
+
+    public boolean shouldDebugNonSafepoints() {
+        return runtime.getCompilerToVM().shouldDebugNonSafepoints();
+    }
+
+    /**
+     * Notifies the VM of statistics for a completed compilation.
+     *
+     * @param id the identifier of the compilation
+     * @param method the method compiled
+     * @param osr specifies if the compilation was for on-stack-replacement
+     * @param processedBytecodes the number of bytecodes processed during the compilation, including
+     *            the bytecodes of all inlined methods
+     * @param time the amount time spent compiling {@code method}
+     * @param timeUnitsPerSecond the granularity of the units for the {@code time} value
+     * @param installedCode the nmethod installed as a result of the compilation
+     */
+    public void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode) {
+        runtime.getCompilerToVM().notifyCompilationStatistics(id, (HotSpotResolvedJavaMethodImpl) method, osr, processedBytecodes, time, timeUnitsPerSecond, installedCode);
+    }
+
+    /**
+     * Resets all compilation statistics.
+     */
+    public void resetCompilationStatistics() {
+        runtime.getCompilerToVM().resetCompilationStatistics();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompilationRequest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.CompilationRequest;
+
+/**
+ * A compilation request with extra HotSpot specific context such as a compilation identifier and
+ * the address of a {@code JVMCIEnv} object that provides native context for a compilation.
+ */
+public class HotSpotCompilationRequest extends CompilationRequest {
+    private final long jvmciEnv;
+    private final int id;
+
+    /**
+     * Creates a request to compile a method starting at a given BCI and allocates an identifier to
+     * the request.
+     *
+     * @param method the method to be compiled
+     * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
+     *            method's entry point
+     * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L
+     */
+    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv) {
+        this(method, entryBCI, jvmciEnv, method.allocateCompileId(entryBCI));
+    }
+
+    /**
+     * Creates a request to compile a method starting at a given BCI.
+     *
+     * @param method the method to be compiled
+     * @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
+     *            method's entry point
+     * @param jvmciEnv address of a native {@code JVMCIEnv} object or 0L
+     * @param id an identifier for the request
+     */
+    public HotSpotCompilationRequest(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+        super(method, entryBCI);
+        this.jvmciEnv = jvmciEnv;
+        this.id = id;
+    }
+
+    @Override
+    public HotSpotResolvedJavaMethod getMethod() {
+        return (HotSpotResolvedJavaMethod) super.getMethod();
+    }
+
+    /**
+     * Gets the address of the native {@code JVMCIEnv} object or 0L if no such object exists.
+     */
+    public long getJvmciEnv() {
+        return jvmciEnv;
+    }
+
+    /**
+     * Gets the VM allocated identifier for this compilation.
+     */
+    public int getId() {
+        return id;
+    }
+
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,12 +22,16 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.nio.*;
-import java.util.*;
-import java.util.stream.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Stream;
 import java.util.stream.Stream.Builder;
 
-import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.code.CompilationResult;
 import jdk.vm.ci.code.CompilationResult.CodeAnnotation;
 import jdk.vm.ci.code.CompilationResult.CodeComment;
 import jdk.vm.ci.code.CompilationResult.DataPatch;
@@ -36,14 +40,15 @@
 import jdk.vm.ci.code.CompilationResult.JumpTable;
 import jdk.vm.ci.code.CompilationResult.Mark;
 import jdk.vm.ci.code.CompilationResult.Site;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.DataSection;
 import jdk.vm.ci.meta.Assumptions.Assumption;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
  * A {@link CompilationResult} with additional HotSpot-specific information required for installing
  * the code in HotSpot's code cache.
  */
-public abstract class HotSpotCompiledCode {
+public class HotSpotCompiledCode {
 
     public final String name;
     public final Site[] sites;
@@ -113,9 +118,7 @@
         targetCodeSize = compResult.getTargetCodeSize();
 
         DataSection data = compResult.getDataSection();
-        if (!data.isFinalized()) {
-            data.finalizeLayout();
-        }
+        data.finalizeLayout();
         dataSection = new byte[data.getSectionSize()];
 
         ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder());
@@ -176,4 +179,9 @@
         Arrays.sort(result, new SiteComparator());
         return result;
     }
+
+    @Override
+    public String toString() {
+        return name;
+    }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,8 +22,8 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.inittimer.*;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.inittimer.SuppressFBWarnings;
 
 /**
  * {@link HotSpotCompiledCode} destined for installation as an nmethod.
@@ -32,8 +32,17 @@
 
     public final HotSpotResolvedJavaMethod method;
     public final int entryBCI;
+
+    /**
+     * Compilation identifier.
+     */
     public final int id;
+
+    /**
+     * Address of a native {@code JVMCIEnv} object or 0L if no such object exists.
+     */
     public final long jvmciEnv;
+
     public final boolean hasUnsafeAccess;
 
     /**
@@ -42,15 +51,11 @@
      */
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "set by the VM") private String installationFailureMessage;
 
-    public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult) {
-        this(method, compResult, 0L);
-    }
-
-    public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, long jvmciEnv) {
+    public HotSpotCompiledNmethod(HotSpotResolvedJavaMethod method, CompilationResult compResult, int id, long jvmciEnv) {
         super(compResult);
         this.method = method;
         this.entryBCI = compResult.getEntryBCI();
-        this.id = compResult.getId();
+        this.id = id;
         this.jvmciEnv = jvmciEnv;
         this.hasUnsafeAccess = compResult.hasUnsafeAccess();
     }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,9 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
 
 /**
  * The compressed representation of the {@link JavaConstant#NULL_POINTER null constant}.
@@ -48,6 +50,14 @@
         return true;
     }
 
+    public Constant compress() {
+        throw new IllegalArgumentException();
+    }
+
+    public Constant uncompress() {
+        return NULL_POINTER;
+    }
+
     @Override
     public boolean isDefaultForKind() {
         return true;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Constant;
 
 /**
  * Marker interface for hotspot specific constants.
@@ -30,4 +30,8 @@
 public interface HotSpotConstant extends Constant {
 
     boolean isCompressed();
+
+    Constant compress();
+
+    Constant uncompress();
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,18 +22,27 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
 
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaField;
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
 
 /**
  * Implementation of {@link ConstantPool} for HotSpot.
  */
-public final class HotSpotConstantPool implements ConstantPool, HotSpotProxified, MetaspaceWrapperObject {
+final class HotSpotConstantPool implements ConstantPool, HotSpotProxified, MetaspaceWrapperObject {
 
     /**
      * Subset of JVM bytecode opcodes used by {@link HotSpotConstantPool}.
@@ -121,10 +130,6 @@
             this.tag = tag;
         }
 
-        private static HotSpotVMConfig config() {
-            return runtime().getConfig();
-        }
-
         /**
          * Maps JVM_CONSTANT tags to {@link JVM_CONSTANT} values. Using a separate class for lazy
          * initialization.
@@ -204,7 +209,7 @@
      * @return holder for this constant pool
      */
     private HotSpotResolvedObjectType getHolder() {
-        return runtime().getCompilerToVM().getResolvedJavaType(this, runtime().getConfig().constantPoolHolderOffset, false);
+        return compilerToVM().getResolvedJavaType(this, config().constantPoolHolderOffset, false);
     }
 
     /**
@@ -224,7 +229,7 @@
         } else {
             assert opcode == Bytecodes.GETFIELD || opcode == Bytecodes.PUTFIELD || opcode == Bytecodes.GETSTATIC || opcode == Bytecodes.PUTSTATIC || opcode == Bytecodes.INVOKEINTERFACE ||
                             opcode == Bytecodes.INVOKEVIRTUAL || opcode == Bytecodes.INVOKESPECIAL || opcode == Bytecodes.INVOKESTATIC : "unexpected invoke opcode " + opcode;
-            index = rawIndex + runtime().getConfig().constantPoolCpCacheIndexTag;
+            index = rawIndex + config().constantPoolCpCacheIndexTag;
         }
         return index;
     }
@@ -241,7 +246,7 @@
         if (isInvokedynamicIndex(index)) {
             return decodeInvokedynamicIndex(index);
         } else {
-            return index - runtime().getConfig().constantPoolCpCacheIndexTag;
+            return index - config().constantPoolCpCacheIndexTag;
         }
     }
 
@@ -260,7 +265,7 @@
         return ~i;
     }
 
-    public long getMetaspaceConstantPool() {
+    long getMetaspaceConstantPool() {
         return metaspaceConstantPool;
     }
 
@@ -276,7 +281,7 @@
      */
     private JVM_CONSTANT getTagAt(int index) {
         assertBounds(index);
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         final long metaspaceConstantPoolTags = UNSAFE.getAddress(getMetaspaceConstantPool() + config.constantPoolTagsOffset);
         final int tag = UNSAFE.getByteVolatile(null, metaspaceConstantPoolTags + config.arrayU1DataOffset + index);
         if (tag == 0) {
@@ -293,7 +298,7 @@
      */
     private long getEntryAt(int index) {
         assertBounds(index);
-        return UNSAFE.getAddress(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
     }
 
     /**
@@ -304,7 +309,7 @@
      */
     private int getIntAt(int index) {
         assertTag(index, JVM_CONSTANT.Integer);
-        return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
     }
 
     /**
@@ -315,7 +320,7 @@
      */
     private long getLongAt(int index) {
         assertTag(index, JVM_CONSTANT.Long);
-        return UNSAFE.getLong(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
     }
 
     /**
@@ -326,7 +331,7 @@
      */
     private float getFloatAt(int index) {
         assertTag(index, JVM_CONSTANT.Float);
-        return UNSAFE.getFloat(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
     }
 
     /**
@@ -337,7 +342,7 @@
      */
     private double getDoubleAt(int index) {
         assertTag(index, JVM_CONSTANT.Double);
-        return UNSAFE.getDouble(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
     }
 
     /**
@@ -348,7 +353,7 @@
      */
     private int getNameAndTypeAt(int index) {
         assertTag(index, JVM_CONSTANT.NameAndType);
-        return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
     }
 
     /**
@@ -359,7 +364,7 @@
      * @return {@code JVM_CONSTANT_NameAndType} reference constant pool entry
      */
     private int getNameAndTypeRefIndexAt(int index) {
-        return runtime().getCompilerToVM().lookupNameAndTypeRefIndexInPool(this, index);
+        return compilerToVM().lookupNameAndTypeRefIndexInPool(this, index);
     }
 
     /**
@@ -370,7 +375,7 @@
      * @return name as {@link String}
      */
     private String getNameOf(int which) {
-        return runtime().getCompilerToVM().lookupNameInPool(this, which);
+        return compilerToVM().lookupNameInPool(this, which);
     }
 
     /**
@@ -394,7 +399,7 @@
      * @return signature as {@link String}
      */
     private String getSignatureOf(int which) {
-        return runtime().getCompilerToVM().lookupSignatureInPool(this, which);
+        return compilerToVM().lookupSignatureInPool(this, which);
     }
 
     /**
@@ -417,7 +422,7 @@
      * @return klass reference index
      */
     private int getKlassRefIndexAt(int index) {
-        return runtime().getCompilerToVM().lookupKlassRefIndexInPool(this, index);
+        return compilerToVM().lookupKlassRefIndexInPool(this, index);
     }
 
     /**
@@ -427,22 +432,11 @@
      * @param index constant pool index
      * @return klass reference index
      */
-    private int getUncachedKlassRefIndexAt(int index, JVM_CONSTANT tag) {
-        int resultIndex;
-        if (tag == JVM_CONSTANT.MethodRef || tag == JVM_CONSTANT.Fieldref || tag == JVM_CONSTANT.InterfaceMethodref) {
-            assertTagIsFieldOrMethod(index);
-            final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
-            // klass ref index is in the low 16-bits.
-            resultIndex = refIndex & 0xFFFF;
-        } else {
-            resultIndex = index;
-        }
-
-        // Read the tag only once because it could change between multiple reads.
-        final JVM_CONSTANT klassTag = getTagAt(resultIndex);
-        assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag;
-
-        return resultIndex;
+    private int getUncachedKlassRefIndexAt(int index) {
+        assertTagIsFieldOrMethod(index);
+        final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        // klass ref index is in the low 16-bits.
+        return refIndex & 0xFFFF;
     }
 
     /**
@@ -478,7 +472,7 @@
 
     @Override
     public int length() {
-        return UNSAFE.getInt(getMetaspaceConstantPool() + runtime().getConfig().constantPoolLengthOffset);
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolLengthOffset);
     }
 
     @Override
@@ -505,13 +499,13 @@
                  * "pseudo strings" (arbitrary live objects) patched into a String entry. Such
                  * entries do not have a symbol in the constant pool slot.
                  */
-                Object string = runtime().getCompilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
+                Object string = compilerToVM().resolvePossiblyCachedConstantInPool(this, cpi);
                 return HotSpotObjectConstantImpl.forObject(string);
             case MethodHandle:
             case MethodHandleInError:
             case MethodType:
             case MethodTypeInError:
-                Object obj = runtime().getCompilerToVM().resolveConstantInPool(this, cpi);
+                Object obj = compilerToVM().resolveConstantInPool(this, cpi);
                 return HotSpotObjectConstantImpl.forObject(obj);
             default:
                 throw new JVMCIError("Unknown constant pool tag %s", tag);
@@ -521,7 +515,7 @@
     @Override
     public String lookupUtf8(int cpi) {
         assertTag(cpi, JVM_CONSTANT.Utf8);
-        return runtime().getCompilerToVM().getSymbol(getEntryAt(cpi));
+        return compilerToVM().getSymbol(getEntryAt(cpi));
     }
 
     @Override
@@ -533,7 +527,7 @@
     public JavaConstant lookupAppendix(int cpi, int opcode) {
         assert Bytecodes.isInvoke(opcode);
         final int index = rawIndexToConstantPoolIndex(cpi, opcode);
-        Object appendix = runtime().getCompilerToVM().lookupAppendixInPool(this, index);
+        Object appendix = compilerToVM().lookupAppendixInPool(this, index);
         if (appendix == null) {
             return null;
         } else {
@@ -558,7 +552,7 @@
     @Override
     public JavaMethod lookupMethod(int cpi, int opcode) {
         final int index = rawIndexToConstantPoolIndex(cpi, opcode);
-        final HotSpotResolvedJavaMethod method = runtime().getCompilerToVM().lookupMethodInPool(this, index, (byte) opcode);
+        final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, index, (byte) opcode);
         if (method != null) {
             return method;
         } else {
@@ -570,7 +564,7 @@
                 return new HotSpotMethodUnresolved(name, signature, holder);
             } else {
                 final int klassIndex = getKlassRefIndexAt(index);
-                final Object type = runtime().getCompilerToVM().lookupKlassInPool(this, klassIndex);
+                final Object type = compilerToVM().lookupKlassInPool(this, klassIndex);
                 JavaType holder = getJavaType(type);
                 return new HotSpotMethodUnresolved(name, signature, holder);
             }
@@ -583,7 +577,7 @@
         if (elem != null && elem.lastCpi == cpi) {
             return elem.javaType;
         } else {
-            final Object type = runtime().getCompilerToVM().lookupKlassInPool(this, cpi);
+            final Object type = compilerToVM().lookupKlassInPool(this, cpi);
             JavaType result = getJavaType(type);
             if (result instanceof ResolvedJavaType) {
                 this.lastLookupType = new LookupTypeCacheElement(cpi, result);
@@ -609,7 +603,7 @@
             long[] info = new long[2];
             HotSpotResolvedObjectTypeImpl resolvedHolder;
             try {
-                resolvedHolder = runtime().getCompilerToVM().resolveFieldInPool(this, index, (byte) opcode, info);
+                resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (byte) opcode, info);
             } catch (Throwable t) {
                 /*
                  * If there was an exception resolving the field we give up and return an unresolved
@@ -643,8 +637,8 @@
                 break;
             case Bytecodes.INVOKEDYNAMIC: {
                 // invokedynamic instructions point to a constant pool cache entry.
-                index = decodeConstantPoolCacheIndex(cpi) + runtime().getConfig().constantPoolCpCacheIndexTag;
-                index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
+                index = decodeConstantPoolCacheIndex(cpi) + config().constantPoolCpCacheIndexTag;
+                index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
                 break;
             }
             case Bytecodes.GETSTATIC:
@@ -657,7 +651,7 @@
             case Bytecodes.INVOKEINTERFACE: {
                 // invoke and field instructions point to a constant pool cache entry.
                 index = rawIndexToConstantPoolIndex(cpi, opcode);
-                index = runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
+                index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
                 break;
             }
             default:
@@ -673,11 +667,15 @@
             case MethodRef:
             case Fieldref:
             case InterfaceMethodref:
+                index = getUncachedKlassRefIndexAt(index);
+                // Read the tag only once because it could change between multiple reads.
+                final JVM_CONSTANT klassTag = getTagAt(index);
+                assert klassTag == JVM_CONSTANT.Class || klassTag == JVM_CONSTANT.UnresolvedClass || klassTag == JVM_CONSTANT.UnresolvedClassInError : klassTag;
+                // fall through
             case Class:
             case UnresolvedClass:
             case UnresolvedClassInError:
-                index = getUncachedKlassRefIndexAt(index, tag);
-                final HotSpotResolvedObjectTypeImpl type = runtime().getCompilerToVM().resolveTypeInPool(this, index);
+                final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, index);
                 Class<?> klass = type.mirror();
                 if (!klass.isPrimitive() && !klass.isArray()) {
                     UNSAFE.ensureClassInitialized(klass);
@@ -687,14 +685,14 @@
                         if (Bytecodes.isInvokeHandleAlias(opcode)) {
                             final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
                             if (isInvokeHandle(methodRefCacheIndex, type)) {
-                                runtime().getCompilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
+                                compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
                             }
                         }
                 }
                 break;
             case InvokeDynamic:
                 if (isInvokedynamicIndex(cpi)) {
-                    runtime().getCompilerToVM().resolveInvokeDynamicInPool(this, cpi);
+                    compilerToVM().resolveInvokeDynamicInPool(this, cpi);
                 }
                 break;
             default:
@@ -704,7 +702,7 @@
     }
 
     private boolean isInvokeHandle(int methodRefCacheIndex, HotSpotResolvedObjectTypeImpl klass) {
-        assertTag(runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
+        assertTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), JVM_CONSTANT.MethodRef);
         return ResolvedJavaMethod.isSignaturePolymorphic(klass, getNameOf(methodRefCacheIndex), runtime().getHostJVMCIBackend().getMetaAccess());
     }
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,12 +22,24 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider.Options.*;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
+
+import java.lang.reflect.Array;
 
-import java.lang.reflect.*;
-
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.options.*;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaField;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.MemoryAccessProvider;
+import jdk.vm.ci.meta.MethodHandleAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.options.Option;
+import jdk.vm.ci.options.OptionType;
+import jdk.vm.ci.options.OptionValue;
+import jdk.vm.ci.options.StableOptionValue;
 
 /**
  * HotSpot implementation of {@link ConstantReflectionProvider}.
@@ -61,11 +73,6 @@
     }
 
     @Override
-    public boolean isEmbeddable(Constant constant) {
-        return true;
-    }
-
-    @Override
     public Boolean constantEquals(Constant x, Constant y) {
         if (x == y) {
             return true;
@@ -110,8 +117,8 @@
         }
         Class<?> componentType = ((HotSpotObjectConstantImpl) array).object().getClass().getComponentType();
         JavaKind kind = runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(componentType).getJavaKind();
-        int arraybase = runtime.getArrayBaseOffset(kind);
-        int scale = runtime.getArrayIndexScale(kind);
+        int arraybase = getArrayBaseOffset(kind);
+        int scale = getArrayIndexScale(kind);
         if (offset < arraybase) {
             return -1;
         }
@@ -207,6 +214,10 @@
         return HotSpotObjectConstantImpl.forObject(value);
     }
 
+    public JavaConstant forObject(Object value) {
+        return HotSpotObjectConstantImpl.forObject(value);
+    }
+
     @Override
     public ResolvedJavaType asJavaType(Constant constant) {
         if (constant instanceof HotSpotObjectConstant) {
@@ -216,7 +227,7 @@
             }
         }
         if (constant instanceof HotSpotMetaspaceConstant) {
-            Object obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant);
+            MetaspaceWrapperObject obj = HotSpotMetaspaceConstantImpl.getMetaspaceObject(constant);
             if (obj instanceof HotSpotResolvedObjectTypeImpl) {
                 return (ResolvedJavaType) obj;
             }
@@ -251,7 +262,7 @@
      *            {@code value} was read
      */
     protected boolean isFinalInstanceFieldValueConstant(JavaConstant value, Class<?> receiverClass) {
-        return !value.isDefaultForKind() || TrustFinalDefaultFields.getValue();
+        return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue();
     }
 
     /**
@@ -327,7 +338,7 @@
         if (!hotspotField.isStable()) {
             return readNonStableFieldValue(field, receiver);
         } else {
-            return readStableFieldValue(field, receiver, false);
+            return readStableFieldValue(field, receiver, hotspotField.isDefaultStable());
         }
     }
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Wed Jul 05 21:00:20 2017 +0200
@@ -23,7 +23,6 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
-
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.inittimer.SuppressFBWarnings;
 import sun.misc.Unsafe;
@@ -59,18 +58,6 @@
         return size;
     }
 
-    /**
-     * @return a copy of this code blob if it is {@linkplain #isValid() valid}, null otherwise.
-     */
-    public byte[] getBlob() {
-        if (!isValid()) {
-            return null;
-        }
-        byte[] blob = new byte[size];
-        UNSAFE.copyMemory(null, getAddress(), blob, Unsafe.ARRAY_BYTE_BASE_OFFSET, size);
-        return blob;
-    }
-
     @Override
     public abstract String toString();
 
@@ -79,7 +66,6 @@
         return codeStart;
     }
 
-    @Override
     public long getCodeSize() {
         return codeSize;
     }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,12 +22,11 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.compiler.*;
-import jdk.vm.ci.runtime.*;
+import jdk.vm.ci.runtime.JVMCIBackend;
 
 public interface HotSpotJVMCIBackendFactory {
 
-    JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host);
+    JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host);
 
     /**
      * Gets the CPU architecture of this backend.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,19 +22,18 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.compiler.*;
-import jdk.vm.ci.compiler.Compiler;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.runtime.*;
-import jdk.vm.ci.service.*;
+import jdk.vm.ci.code.CompilationRequest;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.runtime.JVMCICompiler;
+import jdk.vm.ci.runtime.JVMCICompilerFactory;
+import jdk.vm.ci.runtime.JVMCIRuntime;
+import jdk.vm.ci.service.Services;
 
 final class HotSpotJVMCICompilerConfig {
 
-    private static class DummyCompilerFactory implements CompilerFactory, Compiler {
+    private static class DummyCompilerFactory implements JVMCICompilerFactory, JVMCICompiler {
 
-        public void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
+        public void compileMethod(CompilationRequest request) {
             throw new JVMCIError("no JVMCI compiler selected");
         }
 
@@ -42,16 +41,12 @@
             return "<none>";
         }
 
-        public Architecture initializeArchitecture(Architecture arch) {
-            return arch;
-        }
-
-        public Compiler createCompiler(JVMCIRuntime runtime) {
+        public JVMCICompiler createCompiler(JVMCIRuntime runtime) {
             return this;
         }
     }
 
-    private static CompilerFactory compilerFactory;
+    private static JVMCICompilerFactory compilerFactory;
 
     /**
      * Selects the system compiler.
@@ -61,7 +56,7 @@
      */
     static Boolean selectCompiler(String compilerName) {
         assert compilerFactory == null;
-        for (CompilerFactory factory : Services.load(CompilerFactory.class)) {
+        for (JVMCICompilerFactory factory : Services.load(JVMCICompilerFactory.class)) {
             if (factory.getCompilerName().equals(compilerName)) {
                 compilerFactory = factory;
                 return Boolean.TRUE;
@@ -71,7 +66,7 @@
         throw new JVMCIError("JVMCI compiler '%s' not found", compilerName);
     }
 
-    static CompilerFactory getCompilerFactory() {
+    static JVMCICompilerFactory getCompilerFactory() {
         if (compilerFactory == null) {
             compilerFactory = new DummyCompilerFactory();
         }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,17 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.lang.ref.*;
-import java.util.*;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JVMCIMetaAccessContext;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * This class manages the set of metadata roots that must be scanned during garbage collection.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,54 +22,55 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.inittimer.InitTimer.*;
+import static jdk.vm.ci.inittimer.InitTimer.timer;
 
-import java.util.*;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.TreeMap;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.compiler.*;
-import jdk.vm.ci.compiler.Compiler;
-import jdk.vm.ci.inittimer.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.runtime.*;
-import jdk.vm.ci.service.*;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.inittimer.InitTimer;
+import jdk.vm.ci.meta.JVMCIMetaAccessContext;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
+import jdk.vm.ci.runtime.JVMCIBackend;
+import jdk.vm.ci.runtime.JVMCICompiler;
+import jdk.vm.ci.service.Services;
 
 //JaCoCo Exclude
 
+/**
+ * HotSpot implementation of a JVMCI runtime.
+ *
+ * The initialization of this class is very fragile since it's initialized both through
+ * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and
+ * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class
+ * can't have a static initializer and any required initialization must be done as part of
+ * {@link #runtime()}. This allows the initialization to funnel back through
+ * {@link JVMCI#initialize()} without deadlocking.
+ */
 public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, HotSpotProxified {
 
-    /**
-     * The proper initialization of this class is complex because it's tangled up with the
-     * initialization of the JVMCI and really should only ever be triggered through
-     * {@link JVMCI#getRuntime}. However since {@link #runtime} can also be called directly it
-     * should also trigger proper initialization. To ensure proper ordering, the static initializer
-     * of this class initializes {@link JVMCI} and then access to {@link DelayedInit#instance}
-     * triggers the final initialization of the {@link HotSpotJVMCIRuntime}.
-     */
-    static {
-        JVMCI.initialize();
-    }
-
     @SuppressWarnings("try")
     static class DelayedInit {
         private static final HotSpotJVMCIRuntime instance;
 
         static {
-            try (InitTimer t0 = timer("HotSpotJVMCIRuntime.<clinit>")) {
-                try (InitTimer t = timer("StartupEventListener.beforeJVMCIStartup")) {
-                    for (StartupEventListener l : Services.load(StartupEventListener.class)) {
-                        l.beforeJVMCIStartup();
-                    }
-                }
-
-                try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
-                    instance = new HotSpotJVMCIRuntime();
-                }
-
-                try (InitTimer t = timer("HotSpotJVMCIRuntime.completeInitialization")) {
-                    instance.completeInitialization();
-                }
+            try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
+                instance = new HotSpotJVMCIRuntime();
             }
         }
     }
@@ -78,20 +79,10 @@
      * Gets the singleton {@link HotSpotJVMCIRuntime} object.
      */
     public static HotSpotJVMCIRuntime runtime() {
-        assert DelayedInit.instance != null;
+        JVMCI.initialize();
         return DelayedInit.instance;
     }
 
-    /**
-     * Do deferred initialization.
-     */
-    public void completeInitialization() {
-        compiler = HotSpotJVMCICompilerConfig.getCompilerFactory().createCompiler(this);
-        for (HotSpotVMEventListener vmEventListener : vmEventListeners) {
-            vmEventListener.completeInitialization(this);
-        }
-    }
-
     public static HotSpotJVMCIBackendFactory findFactory(String architecture) {
         for (HotSpotJVMCIBackendFactory factory : Services.load(HotSpotJVMCIBackendFactory.class)) {
             if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
@@ -106,7 +97,7 @@
      * Gets the kind of a word value on the {@linkplain #getHostJVMCIBackend() host} backend.
      */
     public static JavaKind getHostWordKind() {
-        return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordKind;
+        return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind;
     }
 
     protected final CompilerToVM compilerToVm;
@@ -114,16 +105,19 @@
     protected final HotSpotVMConfig config;
     private final JVMCIBackend hostBackend;
 
-    private Compiler compiler;
+    private volatile JVMCICompiler compiler;
     protected final JVMCIMetaAccessContext metaAccessContext;
 
     private final Map<Class<? extends Architecture>, JVMCIBackend> backends = new HashMap<>();
 
     private final Iterable<HotSpotVMEventListener> vmEventListeners;
 
+    @SuppressWarnings("unused") private final String[] trivialPrefixes;
+
     @SuppressWarnings("try")
     private HotSpotJVMCIRuntime() {
         compilerToVm = new CompilerToVM();
+
         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
             config = new HotSpotVMConfig(compilerToVm);
         }
@@ -135,10 +129,8 @@
             factory = findFactory(hostArchitecture);
         }
 
-        CompilerFactory compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
-
         try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
-            hostBackend = registerBackend(factory.createJVMCIBackend(this, compilerFactory, null));
+            hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
         }
 
         vmEventListeners = Services.load(HotSpotVMEventListener.class);
@@ -154,6 +146,12 @@
             context = new HotSpotJVMCIMetaAccessContext();
         }
         metaAccessContext = context;
+
+        if (Boolean.valueOf(System.getProperty("jvmci.printconfig"))) {
+            printConfig(config, compilerToVm);
+        }
+
+        trivialPrefixes = HotSpotJVMCICompilerConfig.getCompilerFactory().getTrivialPrefixes();
     }
 
     private JVMCIBackend registerBackend(JVMCIBackend backend) {
@@ -179,7 +177,14 @@
         return metaAccessContext;
     }
 
-    public Compiler getCompiler() {
+    public JVMCICompiler getCompiler() {
+        if (compiler == null) {
+            synchronized (this) {
+                if (compiler == null) {
+                    compiler = HotSpotJVMCICompilerConfig.getCompilerFactory().createCompiler(this);
+                }
+            }
+        }
         return compiler;
     }
 
@@ -211,7 +216,7 @@
         return backends.get(arch);
     }
 
-    public Map<Class<? extends Architecture>, JVMCIBackend> getBackends() {
+    public Map<Class<? extends Architecture>, JVMCIBackend> getJVMCIBackends() {
         return Collections.unmodifiableMap(backends);
     }
 
@@ -220,7 +225,7 @@
      */
     @SuppressWarnings({"unused"})
     private void compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) {
-        compiler.compileMethod(method, entryBCI, jvmciEnv, id);
+        getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id));
     }
 
     /**
@@ -247,4 +252,105 @@
             vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compResult);
         }
     }
+
+    private static void printConfig(HotSpotVMConfig config, CompilerToVM vm) {
+        Field[] fields = config.getClass().getDeclaredFields();
+        Map<String, Field> sortedFields = new TreeMap<>();
+        for (Field f : fields) {
+            if (!f.isSynthetic() && !Modifier.isStatic(f.getModifiers())) {
+                f.setAccessible(true);
+                sortedFields.put(f.getName(), f);
+            }
+        }
+        for (Field f : sortedFields.values()) {
+            try {
+                String line = String.format("%9s %-40s = %s%n", f.getType().getSimpleName(), f.getName(), pretty(f.get(config)));
+                byte[] lineBytes = line.getBytes();
+                vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
+                vm.flushDebugOutput();
+            } catch (Exception e) {
+            }
+        }
+    }
+
+    private static String pretty(Object value) {
+        if (value == null) {
+            return "null";
+        }
+
+        Class<?> klass = value.getClass();
+        if (value instanceof String) {
+            return "\"" + value + "\"";
+        } else if (value instanceof Method) {
+            return "method \"" + ((Method) value).getName() + "\"";
+        } else if (value instanceof Class<?>) {
+            return "class \"" + ((Class<?>) value).getSimpleName() + "\"";
+        } else if (value instanceof Integer) {
+            if ((Integer) value < 10) {
+                return value.toString();
+            }
+            return value + " (0x" + Integer.toHexString((Integer) value) + ")";
+        } else if (value instanceof Long) {
+            if ((Long) value < 10 && (Long) value > -10) {
+                return value + "l";
+            }
+            return value + "l (0x" + Long.toHexString((Long) value) + "l)";
+        } else if (klass.isArray()) {
+            StringBuilder str = new StringBuilder();
+            int dimensions = 0;
+            while (klass.isArray()) {
+                dimensions++;
+                klass = klass.getComponentType();
+            }
+            int length = Array.getLength(value);
+            str.append(klass.getSimpleName()).append('[').append(length).append(']');
+            for (int i = 1; i < dimensions; i++) {
+                str.append("[]");
+            }
+            str.append(" {");
+            for (int i = 0; i < length; i++) {
+                str.append(pretty(Array.get(value, i)));
+                if (i < length - 1) {
+                    str.append(", ");
+                }
+            }
+            str.append('}');
+            return str.toString();
+        }
+        return value.toString();
+    }
+
+    public OutputStream getLogStream() {
+        return new OutputStream() {
+
+            @Override
+            public void write(byte[] b, int off, int len) throws IOException {
+                if (b == null) {
+                    throw new NullPointerException();
+                } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length || (off + len) < 0) {
+                    throw new IndexOutOfBoundsException();
+                } else if (len == 0) {
+                    return;
+                }
+                compilerToVm.writeDebugOutput(b, off, len);
+            }
+
+            @Override
+            public void write(int b) throws IOException {
+                write(new byte[]{(byte) b}, 0, 1);
+            }
+
+            @Override
+            public void flush() throws IOException {
+                compilerToVm.flushDebugOutput();
+            }
+        };
+    }
+
+    /**
+     * Collects the current values of all JVMCI benchmark counters, summed up over all threads.
+     */
+    public long[] collectCounters() {
+        return compilerToVm.collectCounters();
+    }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,11 +22,15 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.compiler.Compiler;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.runtime.*;
-import sun.misc.*;
+import java.io.OutputStream;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.JVMCIMetaAccessContext;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCIRuntime;
+import sun.misc.Unsafe;
 
 //JaCoCo Exclude
 
@@ -39,7 +43,10 @@
 
     CompilerToVM getCompilerToVM();
 
-    Compiler getCompiler();
+    /**
+     * Gets an output stream that writes to the HotSpot's {@code tty} stream.
+     */
+    OutputStream getLogStream();
 
     /**
      * Converts a name to a Java type. This method attempts to resolve {@code name} to a
@@ -70,7 +77,7 @@
      *
      * @return the offset in bytes
      */
-    default int getArrayBaseOffset(JavaKind kind) {
+    static int getArrayBaseOffset(JavaKind kind) {
         switch (kind) {
             case Boolean:
                 return Unsafe.ARRAY_BOOLEAN_BASE_OFFSET;
@@ -100,7 +107,7 @@
      *
      * @return the scale in order to convert the index into a byte offset
      */
-    default int getArrayIndexScale(JavaKind kind) {
+    static int getArrayIndexScale(JavaKind kind) {
         switch (kind) {
             case Boolean:
                 return Unsafe.ARRAY_BOOLEAN_INDEX_SCALE;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaType;
 
 /**
  * Common base class for all HotSpot {@link JavaType} implementations.
@@ -39,5 +39,4 @@
     public final String getName() {
         return name;
     }
-
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,8 +22,10 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.hotspot.HotSpotVMConfig.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.hotspot.HotSpotVMConfig.CompressEncoding;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.MemoryAccessProvider;
 
 /**
  * HotSpot specific extension of {@link MemoryAccessProvider}.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -23,8 +23,6 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
-
-import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotVMConfig.CompressEncoding;
 import jdk.vm.ci.meta.Constant;
@@ -36,7 +34,7 @@
 /**
  * HotSpot implementation of {@link MemoryAccessProvider}.
  */
-public class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider, HotSpotProxified {
+class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider, HotSpotProxified {
 
     protected final HotSpotJVMCIRuntimeProvider runtime;
 
@@ -54,7 +52,7 @@
 
     private boolean isValidObjectFieldDisplacement(Constant base, long displacement) {
         if (base instanceof HotSpotMetaspaceConstant) {
-            Object metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
             if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
                 if (displacement == runtime.getConfig().classMirrorOffset) {
                     // Klass::_java_mirror is valid for all Klass* values
@@ -68,8 +66,9 @@
     }
 
     private static long asRawPointer(Constant base) {
-        if (base instanceof HotSpotMetaspaceConstant) {
-            return ((HotSpotMetaspaceConstant) base).rawValue();
+        if (base instanceof HotSpotMetaspaceConstantImpl) {
+            MetaspaceWrapperObject meta = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            return meta.getMetaspacePointer();
         } else if (base instanceof PrimitiveConstant) {
             PrimitiveConstant prim = (PrimitiveConstant) base;
             if (prim.getJavaKind().isNumericInteger()) {
@@ -119,7 +118,7 @@
             }
         }
         if (base instanceof HotSpotMetaspaceConstant) {
-            Object metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
+            MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base);
             if (metaspaceObject instanceof HotSpotResolvedObjectTypeImpl) {
                 if (displacement == runtime.getConfig().classMirrorOffset) {
                     assert expected == ((HotSpotResolvedObjectTypeImpl) metaspaceObject).mirror();
@@ -211,8 +210,7 @@
         if (klass == null) {
             return JavaConstant.NULL_POINTER;
         }
-        TargetDescription target = runtime.getHostJVMCIBackend().getCodeCache().getTarget();
-        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(target.wordKind, klass.getMetaspaceKlass(), klass, false);
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, false);
     }
 
     @Override
@@ -221,15 +219,14 @@
         if (klass == null) {
             return HotSpotCompressedNullConstant.COMPRESSED_NULL;
         }
-        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Int, encoding.compress(klass.getMetaspaceKlass()), klass, true);
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(klass, true);
     }
 
     @Override
     public Constant readMethodPointerConstant(Constant base, long displacement) {
-        TargetDescription target = runtime.getHostJVMCIBackend().getCodeCache().getTarget();
         assert (base instanceof HotSpotObjectConstantImpl);
         Object baseObject = ((HotSpotObjectConstantImpl) base).object();
         HotSpotResolvedJavaMethodImpl method = runtime.getCompilerToVM().getResolvedJavaMethod(baseObject, displacement);
-        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(target.wordKind, method.getMetaspaceMethod(), method, false);
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(method, false);
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,14 +22,31 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
+import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.reflect.*;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.CodeUtil;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.DeoptimizationAction;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
 
 // JaCoCo Exclude
 
@@ -292,9 +309,9 @@
                     int length = Array.getLength(((HotSpotObjectConstantImpl) constant).object());
                     ResolvedJavaType elementType = lookupJavaType.getComponentType();
                     JavaKind elementKind = elementType.getJavaKind();
-                    final int headerSize = runtime.getArrayBaseOffset(elementKind);
+                    final int headerSize = getArrayBaseOffset(elementKind);
                     TargetDescription target = runtime.getHostJVMCIBackend().getTarget();
-                    int sizeOfElement = target.getSizeInBytes(elementKind);
+                    int sizeOfElement = getArrayIndexScale(elementKind);
                     int alignment = target.wordSize;
                     int log2ElementSize = CodeUtil.log2(sizeOfElement);
                     return computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,6 +22,8 @@
  */
 package jdk.vm.ci.hotspot;
 
+import jdk.vm.ci.inittimer.SuppressFBWarnings;
+
 public class HotSpotMetaData {
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] pcDescBytes;
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private byte[] scopesDescBytes;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,18 +22,11 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.hotspot.HotSpotVMConfig.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.VMConstant;
 
 public interface HotSpotMetaspaceConstant extends HotSpotConstant, VMConstant {
 
-    Constant compress(CompressEncoding encoding);
-
-    Constant uncompress(CompressEncoding encoding);
-
     HotSpotResolvedObjectType asResolvedJavaType();
 
     HotSpotResolvedJavaMethod asResolvedJavaMethod();
-
-    long rawValue();
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,59 +22,75 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.util.*;
+import java.util.Objects;
 
-import jdk.vm.ci.hotspot.HotSpotVMConfig.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.VMConstant;
 
-public final class HotSpotMetaspaceConstantImpl extends PrimitiveConstant implements HotSpotMetaspaceConstant, VMConstant, HotSpotProxified {
+final class HotSpotMetaspaceConstantImpl implements HotSpotMetaspaceConstant, VMConstant, HotSpotProxified {
 
-    static HotSpotMetaspaceConstantImpl forMetaspaceObject(JavaKind kind, long primitive, Object metaspaceObject, boolean compressed) {
-        return new HotSpotMetaspaceConstantImpl(kind, primitive, metaspaceObject, compressed);
+    static HotSpotMetaspaceConstantImpl forMetaspaceObject(MetaspaceWrapperObject metaspaceObject, boolean compressed) {
+        return new HotSpotMetaspaceConstantImpl(metaspaceObject, compressed);
     }
 
-    static Object getMetaspaceObject(Constant constant) {
+    static MetaspaceWrapperObject getMetaspaceObject(Constant constant) {
         return ((HotSpotMetaspaceConstantImpl) constant).metaspaceObject;
     }
 
-    private final Object metaspaceObject;
+    private final MetaspaceWrapperObject metaspaceObject;
     private final boolean compressed;
 
-    private HotSpotMetaspaceConstantImpl(JavaKind kind, long primitive, Object metaspaceObject, boolean compressed) {
-        super(kind, primitive);
+    private HotSpotMetaspaceConstantImpl(MetaspaceWrapperObject metaspaceObject, boolean compressed) {
         this.metaspaceObject = metaspaceObject;
         this.compressed = compressed;
     }
 
     @Override
     public int hashCode() {
-        return super.hashCode() ^ System.identityHashCode(metaspaceObject);
+        return System.identityHashCode(metaspaceObject) ^ (compressed ? 1 : 2);
     }
 
     @Override
     public boolean equals(Object o) {
-        return o == this || (o instanceof HotSpotMetaspaceConstantImpl && super.equals(o) && Objects.equals(metaspaceObject, ((HotSpotMetaspaceConstantImpl) o).metaspaceObject));
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof HotSpotMetaspaceConstantImpl)) {
+            return false;
+        }
+
+        HotSpotMetaspaceConstantImpl other = (HotSpotMetaspaceConstantImpl) o;
+        return Objects.equals(this.metaspaceObject, other.metaspaceObject) && this.compressed == other.compressed;
+    }
+
+    @Override
+    public String toValueString() {
+        return String.format("meta{%s%s}", metaspaceObject, compressed ? ";compressed" : "");
     }
 
     @Override
     public String toString() {
-        return super.toString() + "{" + metaspaceObject + (compressed ? ";compressed}" : "}");
+        return toValueString();
+    }
+
+    public boolean isDefaultForKind() {
+        return false;
     }
 
     public boolean isCompressed() {
         return compressed;
     }
 
-    public JavaConstant compress(CompressEncoding encoding) {
+    public Constant compress() {
         assert !isCompressed();
-        HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Int, encoding.compress(asLong()), metaspaceObject, true);
+        HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(metaspaceObject, true);
         assert res.isCompressed();
         return res;
     }
 
-    public JavaConstant uncompress(CompressEncoding encoding) {
+    public Constant uncompress() {
         assert isCompressed();
-        HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(JavaKind.Long, encoding.uncompress(asInt()), metaspaceObject, false);
+        HotSpotMetaspaceConstantImpl res = HotSpotMetaspaceConstantImpl.forMetaspaceObject(metaspaceObject, false);
         assert !res.isCompressed();
         return res;
     }
@@ -92,8 +108,4 @@
         }
         return null;
     }
-
-    public long rawValue() {
-        return asLong();
-    }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,12 +22,17 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static java.util.FormattableFlags.*;
-import java.util.*;
+import static java.util.FormattableFlags.ALTERNATE;
+import static java.util.FormattableFlags.LEFT_JUSTIFY;
+import static java.util.FormattableFlags.UPPERCASE;
 
-import jdk.vm.ci.meta.*;
+import java.util.Formattable;
+import java.util.Formatter;
 
-public abstract class HotSpotMethod implements JavaMethod, Formattable /* , JavaMethodContex */{
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+abstract class HotSpotMethod implements JavaMethod, Formattable /* , JavaMethodContex */{
 
     public static String applyFormattingFlagsAndWidth(String s, int flags, int width) {
         if (flags == 0 && width < 0) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,24 +22,31 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static java.lang.String.*;
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static java.lang.String.format;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.util.*;
+import java.util.Arrays;
 
-import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.meta.JavaMethodProfile.*;
-import jdk.vm.ci.meta.JavaTypeProfile.*;
-import sun.misc.*;
+import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.Tag;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaMethodProfile;
+import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod;
+import jdk.vm.ci.meta.JavaTypeProfile;
+import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.TriState;
+import sun.misc.Unsafe;
 
 /**
  * Access to a HotSpot MethodData structure (defined in methodData.hpp).
  */
 public final class HotSpotMethodData {
 
-    private static final HotSpotVMConfig config = runtime().getConfig();
+    private static final HotSpotVMConfig config = config();
     private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(TriState.FALSE);
     private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(TriState.UNKNOWN);
 
@@ -50,16 +57,16 @@
         new BitData(),
         new CounterData(),
         new JumpData(),
-        new TypeCheckData(),
+        new ReceiverTypeData(),
         new VirtualCallData(),
         new RetData(),
         new BranchData(),
         new MultiBranchData(),
         new ArgInfoData(),
-        null, // call_type_data_tag
-        null, // virtual_call_type_data_tag
-        null, // parameters_type_data_tag
-        null, // speculative_trap_data_tag
+        new UnknownProfileData(Tag.CallTypeData),
+        new VirtualCallTypeData(),
+        new UnknownProfileData(Tag.ParametersTypeData),
+        new UnknownProfileData(Tag.SpeculativeTrapData),
     };
     // @formatter:on
 
@@ -127,7 +134,8 @@
         }
 
         HotSpotMethodDataAccessor result = getData(position);
-        assert result != null : "NO_DATA tag is not allowed";
+        final Tag tag = AbstractMethodData.readTag(this, position);
+        assert result != null : "NO_DATA tag is not allowed " + tag;
         return result;
     }
 
@@ -193,12 +201,12 @@
 
     private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) {
         long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
-        return runtime().compilerToVm.getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes);
+        return compilerToVM().getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes);
     }
 
     private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) {
         long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
-        return runtime().compilerToVm.getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false);
+        return compilerToVM().getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false);
     }
 
     private static int truncateLongToInt(long value) {
@@ -266,10 +274,10 @@
         /**
          * Corresponds to {@code exception_seen_flag}.
          */
-        private static final int EXCEPTIONS_MASK = 0x2;
+        private static final int EXCEPTIONS_MASK = 1 << config.bitDataExceptionSeenFlag;
 
         private final Tag tag;
-        private final int staticSize;
+        protected final int staticSize;
 
         protected AbstractMethodData(Tag tag, int staticSize) {
             this.tag = tag;
@@ -291,8 +299,12 @@
         }
 
         @Override
-        public int getSize(HotSpotMethodData data, int position) {
-            return staticSize + getDynamicSize(data, position);
+        public final int getSize(HotSpotMethodData data, int position) {
+            int size = staticSize + getDynamicSize(data, position);
+            // Sanity check against VM
+            int vmSize = HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
+            assert size == vmSize : size + " != " + vmSize;
+            return size;
         }
 
         @Override
@@ -375,7 +387,7 @@
     private static class BitData extends AbstractMethodData {
 
         private static final int BIT_DATA_SIZE = cellIndexToOffset(0);
-        private static final int BIT_DATA_NULL_SEEN_FLAG = 0x01;
+        private static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
 
         private BitData() {
             super(Tag.BitData, BIT_DATA_SIZE);
@@ -399,7 +411,7 @@
     private static class CounterData extends BitData {
 
         private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
-        private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(0);
+        private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
 
         public CounterData() {
             super(Tag.CounterData, COUNTER_DATA_SIZE);
@@ -427,8 +439,8 @@
     private static class JumpData extends AbstractMethodData {
 
         private static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
-        protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(0);
-        protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(1);
+        protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
+        protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
 
         public JumpData() {
             super(Tag.JumpData, JUMP_DATA_SIZE);
@@ -474,11 +486,11 @@
 
     private abstract static class AbstractTypeData extends CounterData {
 
-        protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(2);
+        protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
 
-        protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(1);
-        protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(2);
-        protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(3);
+        protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
+        protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
+        protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset);
 
         protected AbstractTypeData(Tag tag, int staticSize) {
             super(tag, staticSize);
@@ -571,14 +583,18 @@
         }
     }
 
-    private static class TypeCheckData extends AbstractTypeData {
+    private static class ReceiverTypeData extends AbstractTypeData {
 
         private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
-        public TypeCheckData() {
+        public ReceiverTypeData() {
             super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE);
         }
 
+        protected ReceiverTypeData(Tag tag, int staticSize) {
+            super(tag, staticSize);
+        }
+
         @Override
         public int getExecutionCount(HotSpotMethodData data, int position) {
             return -1;
@@ -590,7 +606,7 @@
         }
     }
 
-    private static class VirtualCallData extends AbstractTypeData {
+    private static class VirtualCallData extends ReceiverTypeData {
 
         private static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
         private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
@@ -600,6 +616,10 @@
             super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE);
         }
 
+        protected VirtualCallData(Tag tag, int staticSize) {
+            super(tag, staticSize);
+        }
+
         @Override
         public int getExecutionCount(HotSpotMethodData data, int position) {
             final int typeProfileWidth = config.typeProfileWidth;
@@ -692,6 +712,19 @@
         }
     }
 
+    private static class VirtualCallTypeData extends VirtualCallData {
+
+        public VirtualCallTypeData() {
+            super(Tag.VirtualCallTypeData, 0);
+        }
+
+        @Override
+        protected int getDynamicSize(HotSpotMethodData data, int position) {
+            assert staticSize == 0;
+            return HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
+        }
+    }
+
     private static class RetData extends CounterData {
 
         private static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
@@ -705,7 +738,7 @@
     private static class BranchData extends JumpData {
 
         private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
-        private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(2);
+        private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
 
         public BranchData() {
             super(Tag.BranchData, BRANCH_DATA_SIZE);
@@ -737,8 +770,8 @@
 
     private static class ArrayData extends AbstractMethodData {
 
-        private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(0);
-        protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(1);
+        private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
+        protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
 
         public ArrayData(Tag tag, int staticSize) {
             super(tag, staticSize);
@@ -762,7 +795,7 @@
     private static class MultiBranchData extends ArrayData {
 
         private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
-        private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = 2;
+        private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount;
         private static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
         private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
         private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
@@ -854,6 +887,24 @@
         }
     }
 
+    private static class UnknownProfileData extends AbstractMethodData {
+        public UnknownProfileData(Tag tag) {
+            super(tag, 0);
+        }
+
+        @Override
+        protected int getDynamicSize(HotSpotMethodData data, int position) {
+            assert staticSize == 0;
+            return HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
+        }
+
+        @Override
+        public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
+            // TODO Auto-generated method stub
+            return null;
+        }
+    }
+
     public void setCompiledIRSize(int size) {
         UNSAFE.putInt(metaspaceMethodData + config.methodDataIRSizeOffset, size);
     }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,11 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
-
-import jdk.vm.ci.meta.*;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
+import jdk.vm.ci.meta.JavaMethodProfile;
+import jdk.vm.ci.meta.JavaTypeProfile;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.TriState;
 
 /**
  * Interface for accessor objects that encapsulate the logic for accessing the different kinds of
@@ -62,10 +64,6 @@
             return value;
         }
 
-        private static HotSpotVMConfig config() {
-            return runtime().getConfig();
-        }
-
         public static Tag getEnum(int value) {
             Tag result = values()[value];
             assert value == result.value;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,11 +22,16 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
-import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*;
-
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.MethodHandleAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProvider, HotSpotProxified {
 
@@ -155,6 +160,6 @@
 
         Object object = ((HotSpotObjectConstantImpl) memberName).object();
         /* Read the ResolvedJavaMethod from the injected field MemberName.vmtarget */
-        return runtime().compilerToVm.getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset());
+        return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset());
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,12 +22,14 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.Signature;
 
 /**
  * Implementation of {@link JavaMethod} for unresolved HotSpot methods.
  */
-public final class HotSpotMethodUnresolved extends HotSpotMethod {
+final class HotSpotMethodUnresolved extends HotSpotMethod {
 
     private final Signature signature;
     protected JavaType holder;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,12 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
-
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.meta.*;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
  * Implementation of {@link InstalledCode} for code installed as an nmethod. The nmethod stores a
@@ -45,34 +47,24 @@
     private final HotSpotResolvedJavaMethod method;
 
     private final boolean isDefault;
-    private final boolean isExternal;
 
     public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault) {
-        this(method, name, isDefault, false);
-    }
-
-    public HotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault, boolean isExternal) {
         super(name);
         this.method = method;
         this.isDefault = isDefault;
-        this.isExternal = isExternal;
     }
 
     public boolean isDefault() {
         return isDefault;
     }
 
-    public boolean isExternal() {
-        return isExternal;
-    }
-
     public ResolvedJavaMethod getMethod() {
         return method;
     }
 
     @Override
     public void invalidate() {
-        runtime().getCompilerToVM().invalidateInstalledCode(this);
+        compilerToVM().invalidateInstalledCode(this);
     }
 
     @Override
@@ -105,8 +97,7 @@
     @Override
     public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
         assert checkArgs(args);
-        assert !isExternal();
-        return runtime().getCompilerToVM().executeInstalledCode(args, this);
+        return compilerToVM().executeInstalledCode(args, this);
     }
 
     @Override
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,13 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.lang.invoke.*;
-import java.util.*;
+import java.lang.invoke.CallSite;
+import java.util.Objects;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.VMConstant;
 
 /**
  * Represents a constant non-{@code null} object reference, within the compiler and across the
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,20 +22,26 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.*;
+import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
 
-import java.lang.invoke.*;
-
-import jdk.vm.ci.inittimer.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.inittimer.SuppressFBWarnings;
+import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * Represents a constant non-{@code null} object reference, within the compiler and across the
  * compiler/runtime interface.
  */
-public final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotProxified {
+final class HotSpotObjectConstantImpl implements HotSpotObjectConstant, HotSpotProxified {
 
-    public static JavaConstant forObject(Object object) {
+    static JavaConstant forObject(Object object) {
         return forObject(object, false);
     }
 
@@ -106,21 +112,6 @@
         return object;
     }
 
-    /**
-     * Determines if the object represented by this constant is {@link Object#equals(Object) equal}
-     * to a given object.
-     */
-    public boolean isEqualTo(Object obj) {
-        return object.equals(obj);
-    }
-
-    /**
-     * Gets the class of the object represented by this constant.
-     */
-    public Class<?> getObjectClass() {
-        return object.getClass();
-    }
-
     public boolean isCompressed() {
         return compressed;
     }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotOopMap.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotOopMap.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,6 +22,8 @@
  */
 package jdk.vm.ci.hotspot;
 
+import jdk.vm.ci.inittimer.SuppressFBWarnings;
+
 public class HotSpotOopMap {
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int offset;
     @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "field is set by the native part") private int count;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,11 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaMethodProfile;
+import jdk.vm.ci.meta.JavaTypeProfile;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.TriState;
 
 public final class HotSpotProfilingInfo implements ProfilingInfo, HotSpotProxified {
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,10 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.util.*;
+import java.util.Arrays;
 
-import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.Location;
+import jdk.vm.ci.code.ReferenceMap;
 
 public final class HotSpotReferenceMap extends ReferenceMap {
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ResolvedJavaField;
 
 /**
  * Represents a field in a HotSpot type.
@@ -45,4 +45,12 @@
      * @return true if field has {@link Stable} annotation, false otherwise
      */
     boolean isStable();
+
+    /**
+     * If this field is stable, checks if default values (0, null, etc.) should be considered stable
+     * as well.
+     *
+     * @return true if default values should be considered stable, false otherwise
+     */
+    boolean isDefaultStable();
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,20 +22,27 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
-import static jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl.Options.*;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
 
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.options.*;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.LocationIdentity;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ModifiersProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.options.Option;
+import jdk.vm.ci.options.OptionType;
+import jdk.vm.ci.options.OptionValue;
 
 /**
  * Represents a field in a HotSpot type.
  */
-public class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotProxified {
+class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotProxified {
 
     static class Options {
         //@formatter:off
@@ -91,7 +98,7 @@
         }
     }
 
-    public HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, String name, JavaType type, long offset, int modifiers) {
+    HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, String name, JavaType type, long offset, int modifiers) {
         this.holder = holder;
         this.name = name;
         this.type = type;
@@ -130,7 +137,7 @@
 
     @Override
     public boolean isInternal() {
-        return (modifiers & runtime().getConfig().jvmAccFieldInternal) != 0;
+        return (modifiers & config().jvmAccFieldInternal) != 0;
     }
 
     /**
@@ -183,7 +190,7 @@
 
     @Override
     public boolean isSynthetic() {
-        return (runtime().getConfig().syntheticFlag & modifiers) != 0;
+        return (config().syntheticFlag & modifiers) != 0;
     }
 
     /**
@@ -192,11 +199,11 @@
      * @return true if field has {@link Stable} annotation, false otherwise
      */
     public boolean isStable() {
-        if ((runtime().getConfig().jvmAccFieldStable & modifiers) != 0) {
+        if ((config().jvmAccFieldStable & modifiers) != 0) {
             return true;
         }
         assert getAnnotation(Stable.class) == null;
-        if (ImplicitStableValues.getValue() && isImplicitStableField()) {
+        if (Options.ImplicitStableValues.getValue() && isImplicitStableField()) {
             return true;
         }
         return false;
@@ -243,19 +250,25 @@
     }
 
     private boolean isImplicitStableField() {
-        if (isSynthetic()) {
-            if (isSyntheticImplicitStableField()) {
-                return true;
-            }
-        } else if (isWellKnownImplicitStableField()) {
+        if (isSyntheticEnumSwitchMap()) {
+            return true;
+        }
+        if (isWellKnownImplicitStableField()) {
             return true;
         }
         return false;
     }
 
-    private boolean isSyntheticImplicitStableField() {
-        assert this.isSynthetic();
-        if (isStatic() && isArray()) {
+    public boolean isDefaultStable() {
+        assert this.isStable();
+        if (isSyntheticEnumSwitchMap()) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isSyntheticEnumSwitchMap() {
+        if (isSynthetic() && isStatic() && isArray()) {
             if (isFinal() && name.equals("$VALUES") || name.equals("ENUM$VALUES")) {
                 // generated int[] field for EnumClass::values()
                 return true;
@@ -281,6 +294,7 @@
         }
 
         private static final ResolvedJavaField STRING_VALUE_FIELD;
+
         static {
             try {
                 MetaAccessProvider metaAccess = runtime().getHostJVMCIBackend().getMetaAccess();
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,15 +22,27 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.lang.reflect.*;
+import java.lang.reflect.Modifier;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.options.Option;
+import jdk.vm.ci.options.OptionType;
+import jdk.vm.ci.options.OptionValue;
 
 /**
  * Implementation of {@link JavaMethod} for resolved HotSpot methods.
  */
 public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod {
 
+    public static class Options {
+        // @formatter:off
+        @Option(help = "", type = OptionType.Debug)
+        public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
+        // @formatter:on
+    }
+
     /**
      * Returns true if this method has a {@code CallerSensitive} annotation.
      *
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,29 +22,47 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
-import static jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.Options.*;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod.Options.UseProfilingInformation;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Executable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
 
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.options.*;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.DefaultProfilingInfo;
+import jdk.vm.ci.meta.ExceptionHandler;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.LineNumberTable;
+import jdk.vm.ci.meta.LineNumberTableImpl;
+import jdk.vm.ci.meta.Local;
+import jdk.vm.ci.meta.LocalImpl;
+import jdk.vm.ci.meta.LocalVariableTable;
+import jdk.vm.ci.meta.LocalVariableTableImpl;
+import jdk.vm.ci.meta.ModifiersProvider;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.TriState;
 
 /**
  * Implementation of {@link JavaMethod} for resolved HotSpot methods.
  */
-public final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified, MetaspaceWrapperObject {
-
-    public static class Options {
-        // @formatter:off
-        @Option(help = "", type = OptionType.Debug)
-        public static final OptionValue<Boolean> UseProfilingInformation = new OptionValue<>(true);
-        // @formatter:on
-    }
+final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSpotResolvedJavaMethod, HotSpotProxified, MetaspaceWrapperObject {
 
     /**
      * Reference to metaspace Method object.
@@ -56,7 +74,7 @@
     private final HotSpotSignature signature;
     private HotSpotMethodData methodData;
     private byte[] code;
-    private Member toJavaCache;
+    private Executable toJavaCache;
 
     /**
      * Gets the holder of a HotSpot metaspace method native object.
@@ -66,10 +84,10 @@
      *         {@code metaspaceMethod}
      */
     private static HotSpotResolvedObjectTypeImpl getHolder(long metaspaceMethod) {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         final long metaspaceConstMethod = UNSAFE.getAddress(metaspaceMethod + config.methodConstMethodOffset);
         final long metaspaceConstantPool = UNSAFE.getAddress(metaspaceConstMethod + config.constMethodConstantsOffset);
-        return runtime().getCompilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false);
+        return compilerToVM().getResolvedJavaType(null, metaspaceConstantPool + config.constantPoolHolderOffset, false);
     }
 
     /**
@@ -94,7 +112,7 @@
         this.metaspaceMethod = metaspaceMethod;
         this.holder = holder;
 
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         final long constMethod = getConstMethod();
 
         /*
@@ -106,7 +124,7 @@
         if (metaspaceConstantPool == holder.getConstantPool().getMetaspaceConstantPool()) {
             this.constantPool = holder.getConstantPool();
         } else {
-            this.constantPool = runtime().getCompilerToVM().getConstantPool(null, constMethod + config.constMethodConstantsOffset);
+            this.constantPool = compilerToVM().getConstantPool(null, constMethod + config.constMethodConstantsOffset);
         }
 
         final int nameIndex = UNSAFE.getChar(constMethod + config.constMethodNameIndexOffset);
@@ -126,7 +144,7 @@
      */
     private long getConstMethod() {
         assert metaspaceMethod != 0;
-        return UNSAFE.getAddress(metaspaceMethod + runtime().getConfig().methodConstMethodOffset);
+        return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset);
     }
 
     @Override
@@ -152,7 +170,7 @@
      * @return flags of this method
      */
     private int getFlags() {
-        return UNSAFE.getByte(metaspaceMethod + runtime().getConfig().methodFlagsOffset);
+        return UNSAFE.getByte(metaspaceMethod + config().methodFlagsOffset);
     }
 
     /**
@@ -161,7 +179,7 @@
      * @return flags of this method's ConstMethod
      */
     private int getConstMethodFlags() {
-        return UNSAFE.getChar(getConstMethod() + runtime().getConfig().constMethodFlagsOffset);
+        return UNSAFE.getChar(getConstMethod() + config().constMethodFlagsOffset);
     }
 
     @Override
@@ -172,20 +190,16 @@
     /**
      * Gets the address of the C++ Method object for this method.
      */
-    public JavaConstant getMetaspaceMethodConstant() {
-        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(getHostWordKind(), metaspaceMethod, this, false);
+    public Constant getMetaspaceMethodConstant() {
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
     }
 
-    public long getMetaspaceMethod() {
+    public long getMetaspacePointer() {
         return metaspaceMethod;
     }
 
-    public long getMetaspacePointer() {
-        return getMetaspaceMethod();
-    }
-
     @Override
-    public JavaConstant getEncoding() {
+    public Constant getEncoding() {
         return getMetaspaceMethodConstant();
     }
 
@@ -194,7 +208,7 @@
      * modifiers as well as the HotSpot internal modifiers.
      */
     public int getAllModifiers() {
-        return UNSAFE.getInt(metaspaceMethod + runtime().getConfig().methodAccessFlagsOffset);
+        return UNSAFE.getInt(metaspaceMethod + config().methodAccessFlagsOffset);
     }
 
     @Override
@@ -213,7 +227,7 @@
             return null;
         }
         if (code == null && holder.isLinked()) {
-            code = runtime().getCompilerToVM().getBytecode(this);
+            code = compilerToVM().getBytecode(this);
             assert code.length == getCodeSize() : "expected: " + getCodeSize() + ", actual: " + code.length;
         }
         return code;
@@ -221,20 +235,20 @@
 
     @Override
     public int getCodeSize() {
-        return UNSAFE.getChar(getConstMethod() + runtime().getConfig().constMethodCodeSizeOffset);
+        return UNSAFE.getChar(getConstMethod() + config().constMethodCodeSizeOffset);
     }
 
     @Override
     public ExceptionHandler[] getExceptionHandlers() {
-        final boolean hasExceptionTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasExceptionTable) != 0;
+        final boolean hasExceptionTable = (getConstMethodFlags() & config().constMethodHasExceptionTable) != 0;
         if (!hasExceptionTable) {
             return new ExceptionHandler[0];
         }
 
-        HotSpotVMConfig config = runtime().getConfig();
-        final int exceptionTableLength = runtime().getCompilerToVM().getExceptionTableLength(this);
+        HotSpotVMConfig config = config();
+        final int exceptionTableLength = compilerToVM().getExceptionTableLength(this);
         ExceptionHandler[] handlers = new ExceptionHandler[exceptionTableLength];
-        long exceptionTableElement = runtime().getCompilerToVM().getExceptionTableStart(this);
+        long exceptionTableElement = compilerToVM().getExceptionTableStart(this);
 
         for (int i = 0; i < exceptionTableLength; i++) {
             final int startPc = UNSAFE.getChar(exceptionTableElement + config.exceptionTableElementStartPcOffset);
@@ -273,7 +287,7 @@
      * @return true if CallerSensitive annotation present, false otherwise
      */
     public boolean isCallerSensitive() {
-        return (getFlags() & runtime().getConfig().methodFlagsCallerSensitive) != 0;
+        return (getFlags() & config().methodFlagsCallerSensitive) != 0;
     }
 
     /**
@@ -282,7 +296,7 @@
      * @return true if ForceInline annotation present, false otherwise
      */
     public boolean isForceInline() {
-        return (getFlags() & runtime().getConfig().methodFlagsForceInline) != 0;
+        return (getFlags() & config().methodFlagsForceInline) != 0;
     }
 
     /**
@@ -291,14 +305,14 @@
      * @return true if DontInline annotation present, false otherwise
      */
     public boolean isDontInline() {
-        return (getFlags() & runtime().getConfig().methodFlagsDontInline) != 0;
+        return (getFlags() & config().methodFlagsDontInline) != 0;
     }
 
     /**
      * Manually adds a DontInline annotation to this method.
      */
     public void setNotInlineable() {
-        runtime().getCompilerToVM().doNotInlineOrCompile(this);
+        compilerToVM().doNotInlineOrCompile(this);
     }
 
     /**
@@ -308,7 +322,7 @@
      * @return true if special method ignored by security stack walks, false otherwise
      */
     public boolean ignoredBySecurityStackWalk() {
-        return runtime().getCompilerToVM().methodIsIgnoredBySecurityStackWalk(this);
+        return compilerToVM().methodIsIgnoredBySecurityStackWalk(this);
     }
 
     @Override
@@ -326,7 +340,7 @@
         if (isAbstract() || isNative()) {
             return 0;
         }
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         return UNSAFE.getChar(getConstMethod() + config.methodMaxLocalsOffset);
     }
 
@@ -335,7 +349,7 @@
         if (isAbstract() || isNative()) {
             return 0;
         }
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         return config.extraStackEntries + UNSAFE.getChar(getConstMethod() + config.constMethodMaxStackOffset);
     }
 
@@ -343,10 +357,10 @@
     public StackTraceElement asStackTraceElement(int bci) {
         if (bci < 0 || bci >= getCodeSize()) {
             // HotSpot code can only construct stack trace elements for valid bcis
-            StackTraceElement ste = runtime().getCompilerToVM().getStackTraceElement(this, 0);
+            StackTraceElement ste = compilerToVM().getStackTraceElement(this, 0);
             return new StackTraceElement(ste.getClassName(), ste.getMethodName(), ste.getFileName(), -1);
         }
-        return runtime().getCompilerToVM().getStackTraceElement(this, bci);
+        return compilerToVM().getStackTraceElement(this, bci);
     }
 
     public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) {
@@ -361,7 +375,11 @@
             // seeing A.foo().
             return null;
         }
-        return runtime().getCompilerToVM().findUniqueConcreteMethod(((HotSpotResolvedObjectTypeImpl) receiver), this);
+        if (this.isDefault()) {
+            // CHA for default methods doesn't work and may crash the VM
+            return null;
+        }
+        return compilerToVM().findUniqueConcreteMethod(((HotSpotResolvedObjectTypeImpl) receiver), this);
     }
 
     @Override
@@ -375,7 +393,7 @@
      * @return the value of {@code Method::_code}
      */
     private long getCompiledCode() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         return UNSAFE.getAddress(metaspaceMethod + config.methodCodeOffset);
     }
 
@@ -395,7 +413,7 @@
     public boolean hasCompiledCodeAtLevel(int level) {
         long compiledCode = getCompiledCode();
         if (compiledCode != 0) {
-            return UNSAFE.getInt(compiledCode + runtime().getConfig().nmethodCompLevelOffset) == level;
+            return UNSAFE.getInt(compiledCode + config().nmethodCompLevelOffset) == level;
         }
         return false;
     }
@@ -407,7 +425,7 @@
         ProfilingInfo info;
 
         if (UseProfilingInformation.getValue() && methodData == null) {
-            long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + runtime().getConfig().methodDataOffset);
+            long metaspaceMethodData = UNSAFE.getAddress(metaspaceMethod + config().methodDataOffset);
             if (metaspaceMethodData != 0) {
                 methodData = new HotSpotMethodData(metaspaceMethodData, this);
                 if (TraceMethodDataFilter != null && this.format("%H.%n").contains(TraceMethodDataFilter)) {
@@ -429,7 +447,7 @@
 
     @Override
     public void reprofile() {
-        runtime().getCompilerToVM().reprofile(this);
+        compilerToVM().reprofile(this);
     }
 
     @Override
@@ -439,31 +457,19 @@
 
     @Override
     public Annotation[][] getParameterAnnotations() {
-        if (isConstructor()) {
-            Constructor<?> javaConstructor = toJavaConstructor();
-            return javaConstructor == null ? null : javaConstructor.getParameterAnnotations();
-        }
-        Method javaMethod = toJava();
+        Executable javaMethod = toJava();
         return javaMethod == null ? null : javaMethod.getParameterAnnotations();
     }
 
     @Override
     public Annotation[] getAnnotations() {
-        if (isConstructor()) {
-            Constructor<?> javaConstructor = toJavaConstructor();
-            return javaConstructor == null ? new Annotation[0] : javaConstructor.getAnnotations();
-        }
-        Method javaMethod = toJava();
+        Executable javaMethod = toJava();
         return javaMethod == null ? new Annotation[0] : javaMethod.getAnnotations();
     }
 
     @Override
     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
-        if (isConstructor()) {
-            Constructor<?> javaConstructor = toJavaConstructor();
-            return javaConstructor == null ? null : javaConstructor.getAnnotation(annotationClass);
-        }
-        Method javaMethod = toJava();
+        Executable javaMethod = toJava();
         return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass);
     }
 
@@ -478,11 +484,7 @@
 
     @Override
     public Type[] getGenericParameterTypes() {
-        if (isConstructor()) {
-            Constructor<?> javaConstructor = toJavaConstructor();
-            return javaConstructor == null ? null : javaConstructor.getGenericParameterTypes();
-        }
-        Method javaMethod = toJava();
+        Executable javaMethod = toJava();
         return javaMethod == null ? null : javaMethod.getGenericParameterTypes();
     }
 
@@ -498,25 +500,13 @@
         return result;
     }
 
-    private Method toJava() {
+    private Executable toJava() {
         if (toJavaCache != null) {
-            return (Method) toJavaCache;
+            return toJavaCache;
         }
         try {
-            Method result = holder.mirror().getDeclaredMethod(name, signatureToTypes());
-            toJavaCache = result;
-            return result;
-        } catch (NoSuchMethodException | NoClassDefFoundError e) {
-            return null;
-        }
-    }
-
-    private Constructor<?> toJavaConstructor() {
-        if (toJavaCache != null) {
-            return (Constructor<?>) toJavaCache;
-        }
-        try {
-            Constructor<?> result = holder.mirror().getDeclaredConstructor(signatureToTypes());
+            Class<?>[] parameterTypes = signatureToTypes();
+            Executable result = isConstructor() ? holder.mirror().getDeclaredConstructor(parameterTypes) : holder.mirror().getDeclaredMethod(name, parameterTypes);
             toJavaCache = result;
             return result;
         } catch (NoSuchMethodException | NoClassDefFoundError e) {
@@ -529,7 +519,7 @@
         if (isDontInline()) {
             return false;
         }
-        return runtime().getCompilerToVM().canInlineMethod(this);
+        return compilerToVM().canInlineMethod(this);
     }
 
     @Override
@@ -537,17 +527,17 @@
         if (isForceInline()) {
             return true;
         }
-        return runtime().getCompilerToVM().shouldInlineMethod(this);
+        return compilerToVM().shouldInlineMethod(this);
     }
 
     @Override
     public LineNumberTable getLineNumberTable() {
-        final boolean hasLineNumberTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasLineNumberTable) != 0;
+        final boolean hasLineNumberTable = (getConstMethodFlags() & config().constMethodHasLineNumberTable) != 0;
         if (!hasLineNumberTable) {
             return null;
         }
 
-        long[] values = runtime().getCompilerToVM().getLineNumberTable(this);
+        long[] values = compilerToVM().getLineNumberTable(this);
         if (values == null || values.length == 0) {
             // Empty table so treat is as non-existent
             return null;
@@ -566,14 +556,14 @@
 
     @Override
     public LocalVariableTable getLocalVariableTable() {
-        final boolean hasLocalVariableTable = (getConstMethodFlags() & runtime().getConfig().constMethodHasLocalVariableTable) != 0;
+        final boolean hasLocalVariableTable = (getConstMethodFlags() & config().constMethodHasLocalVariableTable) != 0;
         if (!hasLocalVariableTable) {
             return null;
         }
 
-        HotSpotVMConfig config = runtime().getConfig();
-        long localVariableTableElement = runtime().getCompilerToVM().getLocalVariableTableStart(this);
-        final int localVariableTableLength = runtime().getCompilerToVM().getLocalVariableTableLength(this);
+        HotSpotVMConfig config = config();
+        long localVariableTableElement = compilerToVM().getLocalVariableTableStart(this);
+        final int localVariableTableLength = compilerToVM().getLocalVariableTableLength(this);
         Local[] locals = new Local[localVariableTableLength];
 
         for (int i = 0; i < localVariableTableLength; i++) {
@@ -606,7 +596,7 @@
         if (!isInVirtualMethodTable(resolved)) {
             throw new JVMCIError("%s does not have a vtable entry in type %s", this, resolved);
         }
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         final int vtableIndex = getVtableIndex((HotSpotResolvedObjectTypeImpl) resolved);
         return config.instanceKlassVtableStartOffset() + vtableIndex * config.vtableEntrySize + config.vtableEntryMethodOffset;
     }
@@ -623,11 +613,11 @@
 
     private int getVtableIndex(HotSpotResolvedObjectTypeImpl resolved) {
         if (!holder.isLinked()) {
-            return runtime().getConfig().invalidVtableIndex;
+            return config().invalidVtableIndex;
         }
         if (holder.isInterface()) {
             if (resolved.isInterface()) {
-                return runtime().getConfig().invalidVtableIndex;
+                return config().invalidVtableIndex;
             }
             return getVtableIndexForInterfaceMethod(resolved);
         }
@@ -640,8 +630,8 @@
      * @return virtual table index
      */
     private int getVtableIndex() {
-        assert!holder.isInterface();
-        HotSpotVMConfig config = runtime().getConfig();
+        assert !holder.isInterface();
+        HotSpotVMConfig config = config();
         int result = UNSAFE.getInt(metaspaceMethod + config.methodVtableIndexOffset);
         assert result >= config.nonvirtualVtableIndex : "must be linked";
         return result;
@@ -649,7 +639,7 @@
 
     private int getVtableIndexForInterfaceMethod(ResolvedJavaType resolved) {
         HotSpotResolvedObjectTypeImpl hotspotType = (HotSpotResolvedObjectTypeImpl) resolved;
-        return runtime().getCompilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this);
+        return compilerToVM().getVtableIndexForInterfaceMethod(hotspotType, this);
     }
 
     /**
@@ -682,14 +672,14 @@
     }
 
     public int intrinsicId() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         return UNSAFE.getChar(metaspaceMethod + config.methodIntrinsicIdOffset);
     }
 
     @Override
     public JavaConstant invoke(JavaConstant receiver, JavaConstant[] arguments) {
-        assert!isConstructor();
-        Method javaMethod = toJava();
+        assert !isConstructor();
+        Method javaMethod = (Method) toJava();
         javaMethod.setAccessible(true);
 
         Object[] objArguments = new Object[arguments.length];
@@ -714,13 +704,13 @@
      * @return compile id
      */
     public int allocateCompileId(int entryBCI) {
-        return runtime().getCompilerToVM().allocateCompileId(this, entryBCI);
+        return compilerToVM().allocateCompileId(this, entryBCI);
     }
 
     public boolean hasCodeAtLevel(int entryBCI, int level) {
-        if (entryBCI == runtime().getConfig().invocationEntryBci) {
+        if (entryBCI == config().invocationEntryBci) {
             return hasCompiledCodeAtLevel(level);
         }
-        return runtime().getCompilerToVM().hasCompiledCodeForOSR(this, entryBCI, level);
+        return compilerToVM().hasCompiledCodeForOSR(this, entryBCI, level);
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,11 +22,11 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType {
 
-    public HotSpotResolvedJavaType(String name) {
+    HotSpotResolvedJavaType(String name) {
         super(name);
     }
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,14 +22,30 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.meta.Assumptions.*;
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
  */
 public interface HotSpotResolvedObjectType extends ResolvedJavaType {
 
+    /**
+     * Gets the JVMCI mirror for a {@link Class} object.
+     *
+     * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
+     */
+    static HotSpotResolvedObjectType fromObjectClass(Class<?> javaClass) {
+        return HotSpotResolvedObjectTypeImpl.fromObjectClass(javaClass);
+    }
+
     HotSpotResolvedObjectType getArrayClass();
 
     ResolvedJavaType getComponentType();
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,24 +22,44 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static java.util.Objects.*;
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static java.util.Objects.requireNonNull;
+import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.nio.*;
-import java.util.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.meta.Assumptions.*;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+import jdk.vm.ci.meta.Assumptions.ConcreteMethod;
+import jdk.vm.ci.meta.Assumptions.ConcreteSubtype;
+import jdk.vm.ci.meta.Assumptions.LeafType;
+import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.MetaUtil;
+import jdk.vm.ci.meta.ModifiersProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.TrustedInterface;
 
 /**
  * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes.
  */
-public final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, HotSpotProxified, MetaspaceWrapperObject {
+final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, HotSpotProxified, MetaspaceWrapperObject {
 
     /**
      * The Java class this type represents.
@@ -58,7 +78,7 @@
      *
      * @return the {@link HotSpotResolvedJavaType} corresponding to {@code javaClass}
      */
-    public static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
+    static HotSpotResolvedObjectTypeImpl fromObjectClass(Class<?> javaClass) {
         return (HotSpotResolvedObjectTypeImpl) runtime().fromClass(javaClass);
     }
 
@@ -108,11 +128,11 @@
     /**
      * Gets the metaspace Klass for this type.
      */
-    public long getMetaspaceKlass() {
+    long getMetaspaceKlass() {
         if (HotSpotJVMCIRuntime.getHostWordKind() == JavaKind.Long) {
-            return UNSAFE.getLong(javaClass, (long) runtime().getConfig().klassOffset);
+            return UNSAFE.getLong(javaClass, (long) config().klassOffset);
         }
-        return UNSAFE.getInt(javaClass, (long) runtime().getConfig().klassOffset) & 0xFFFFFFFFL;
+        return UNSAFE.getInt(javaClass, (long) config().klassOffset) & 0xFFFFFFFFL;
     }
 
     public long getMetaspacePointer() {
@@ -129,7 +149,7 @@
     }
 
     public int getAccessFlags() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         return UNSAFE.getInt(getMetaspaceKlass() + config.klassAccessFlagsOffset);
     }
 
@@ -149,7 +169,7 @@
 
     @Override
     public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         if (isArray()) {
             return getElementalType().isLeaf() ? new AssumptionResult<>(this) : null;
         } else if (isInterface()) {
@@ -214,7 +234,7 @@
      * @return value of the subklass field as metaspace klass pointer
      */
     private HotSpotResolvedObjectTypeImpl getSubklass() {
-        return runtime().getCompilerToVM().getResolvedJavaType(this, runtime().getConfig().subklassOffset, false);
+        return compilerToVM().getResolvedJavaType(this, config().subklassOffset, false);
     }
 
     @Override
@@ -241,7 +261,7 @@
         if (!isInterface()) {
             throw new JVMCIError("Cannot call getSingleImplementor() on a non-interface type: %s", this);
         }
-        return runtime().getCompilerToVM().getImplementor(this);
+        return compilerToVM().getImplementor(this);
     }
 
     public HotSpotResolvedObjectTypeImpl getSupertype() {
@@ -289,14 +309,14 @@
     }
 
     @Override
-    public JavaConstant getObjectHub() {
+    public Constant getObjectHub() {
         return klass();
     }
 
     @Override
     public AssumptionResult<Boolean> hasFinalizableSubclass() {
         assert !isArray();
-        if (!runtime().getCompilerToVM().hasFinalizableSubclass(this)) {
+        if (!compilerToVM().hasFinalizableSubclass(this)) {
             return new AssumptionResult<>(false, new NoFinalizableSubclass(this));
         }
         return new AssumptionResult<>(true);
@@ -304,7 +324,7 @@
 
     @Override
     public boolean hasFinalizer() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         return (getAccessFlags() & config.klassHasFinalizerFlag) != 0;
     }
 
@@ -320,12 +340,12 @@
 
     @Override
     public boolean isInitialized() {
-        return isArray() ? true : getInitState() == runtime().getConfig().instanceKlassStateFullyInitialized;
+        return isArray() ? true : getInitState() == config().instanceKlassStateFullyInitialized;
     }
 
     @Override
     public boolean isLinked() {
-        return isArray() ? true : getInitState() >= runtime().getConfig().instanceKlassStateLinked;
+        return isArray() ? true : getInitState() >= config().instanceKlassStateLinked;
     }
 
     /**
@@ -336,7 +356,7 @@
      */
     private int getInitState() {
         assert !isArray() : "_init_state only exists in InstanceKlass";
-        return UNSAFE.getByte(getMetaspaceKlass() + runtime().getConfig().instanceKlassInitStateOffset) & 0xFF;
+        return UNSAFE.getByte(getMetaspaceKlass() + config().instanceKlassInitStateOffset) & 0xFF;
     }
 
     @Override
@@ -405,12 +425,12 @@
         }
         HotSpotResolvedJavaMethodImpl hotSpotMethod = (HotSpotResolvedJavaMethodImpl) method;
         HotSpotResolvedObjectTypeImpl hotSpotCallerType = (HotSpotResolvedObjectTypeImpl) callerType;
-        return runtime().getCompilerToVM().resolveMethod(this, hotSpotMethod, hotSpotCallerType);
+        return compilerToVM().resolveMethod(this, hotSpotMethod, hotSpotCallerType);
     }
 
     public HotSpotConstantPool getConstantPool() {
         if (constantPool == null) {
-            constantPool = runtime().getCompilerToVM().getConstantPool(this, runtime().getConfig().instanceKlassConstantsOffset);
+            constantPool = compilerToVM().getConstantPool(this, config().instanceKlassConstantsOffset);
         }
         return constantPool;
     }
@@ -424,7 +444,7 @@
         assert !isArray();
         assert !isInterface();
 
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         final int layoutHelper = layoutHelper();
         assert layoutHelper > config.klassLayoutHelperNeutralValue : "must be instance";
 
@@ -438,7 +458,7 @@
     }
 
     public int layoutHelper() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         return UNSAFE.getInt(getMetaspaceKlass() + config.klassLayoutHelperOffset);
     }
 
@@ -458,7 +478,7 @@
     }
 
     public int getVtableLength() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         if (isInterface() || isArray()) {
             /* Everything has the core vtable of java.lang.Object */
             return config.baseVtableLength();
@@ -547,7 +567,7 @@
          * @param index index to the fields array
          */
         public FieldInfo(int index) {
-            HotSpotVMConfig config = runtime().getConfig();
+            HotSpotVMConfig config = config();
             // Get Klass::_fields
             final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
             assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";
@@ -555,19 +575,19 @@
         }
 
         private int getAccessFlags() {
-            return readFieldSlot(runtime().getConfig().fieldInfoAccessFlagsOffset);
+            return readFieldSlot(config().fieldInfoAccessFlagsOffset);
         }
 
         private int getNameIndex() {
-            return readFieldSlot(runtime().getConfig().fieldInfoNameIndexOffset);
+            return readFieldSlot(config().fieldInfoNameIndexOffset);
         }
 
         private int getSignatureIndex() {
-            return readFieldSlot(runtime().getConfig().fieldInfoSignatureIndexOffset);
+            return readFieldSlot(config().fieldInfoSignatureIndexOffset);
         }
 
         public int getOffset() {
-            HotSpotVMConfig config = runtime().getConfig();
+            HotSpotVMConfig config = config();
             final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset);
             final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset);
             final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize;
@@ -606,7 +626,7 @@
         }
 
         private boolean isInternal() {
-            return (getAccessFlags() & runtime().getConfig().jvmAccFieldInternal) != 0;
+            return (getAccessFlags() & config().jvmAccFieldInternal) != 0;
         }
 
         public boolean isStatic() {
@@ -614,7 +634,7 @@
         }
 
         public boolean hasGenericSignature() {
-            return (getAccessFlags() & runtime().getConfig().jvmAccFieldHasGenericSignature) != 0;
+            return (getAccessFlags() & config().jvmAccFieldHasGenericSignature) != 0;
         }
     }
 
@@ -707,7 +727,7 @@
      * See {@code FieldStreamBase::init_generic_signature_start_slot}
      */
     private int getFieldCount() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
         int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
         int fieldCount = 0;
@@ -729,7 +749,7 @@
 
     @Override
     public String getSourceFileName() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         final int sourceFileNameIndex = UNSAFE.getChar(getMetaspaceKlass() + config.instanceKlassSourceFileNameIndexOffset);
         if (sourceFileNameIndex == 0) {
             return null;
@@ -784,21 +804,21 @@
     /**
      * Gets the metaspace Klass boxed in a {@link JavaConstant}.
      */
-    public JavaConstant klass() {
-        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(runtime().getHostJVMCIBackend().getTarget().wordKind, getMetaspaceKlass(), this, false);
+    public Constant klass() {
+        return HotSpotMetaspaceConstantImpl.forMetaspaceObject(this, false);
     }
 
     public boolean isPrimaryType() {
-        return runtime().getConfig().secondarySuperCacheOffset != superCheckOffset();
+        return config().secondarySuperCacheOffset != superCheckOffset();
     }
 
     public int superCheckOffset() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         return UNSAFE.getInt(getMetaspaceKlass() + config.superCheckOffsetOffset);
     }
 
     public long prototypeMarkWord() {
-        HotSpotVMConfig config = runtime().getConfig();
+        HotSpotVMConfig config = config();
         if (isArray()) {
             return config.arrayPrototypeMarkWord();
         } else {
@@ -874,7 +894,7 @@
     }
 
     public ResolvedJavaMethod getClassInitializer() {
-        return runtime().getCompilerToVM().getClassInitializer(this);
+        return compilerToVM().getClassInitializer(this);
     }
 
     @Override
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,15 +22,21 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static java.util.Objects.*;
+import static java.util.Objects.requireNonNull;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Modifier;
+import java.net.URL;
 
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.net.*;
-
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * Implementation of {@link JavaType} for primitive HotSpot types.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotRuntimeStub.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Implementation of {@link InstalledCode} for code installed as a RuntimeStub.
+ */
+public class HotSpotRuntimeStub extends HotSpotInstalledCode {
+
+    public HotSpotRuntimeStub(String name) {
+        super(name);
+    }
+
+    public ResolvedJavaMethod getMethod() {
+        return null;
+    }
+
+    @Override
+    public boolean isValid() {
+        return true;
+    }
+
+    @Override
+    public void invalidate() {
+    }
+
+    @Override
+    public String toString() {
+        return String.format("InstalledRuntimeStub[stub=%s, codeBlob=0x%x]", name, getAddress());
+    }
+
+    @Override
+    public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        throw new InternalError("Cannot call stub " + name);
+    }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,16 +22,23 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.VMConstant;
+import jdk.vm.ci.meta.Value;
 
 public final class HotSpotSentinelConstant extends Value implements JavaConstant, VMConstant {
 
-    public HotSpotSentinelConstant(JavaKind kind) {
-        super(LIRKind.reference(kind));
+    private final JavaKind javaKind;
+
+    public HotSpotSentinelConstant(LIRKind lirKind, JavaKind javaKind) {
+        super(lirKind);
+        this.javaKind = javaKind;
     }
 
     public JavaKind getJavaKind() {
-        return (JavaKind) getLIRKind().getPlatformKind();
+        return javaKind;
     }
 
     @Override
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,14 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
 
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
 
 /**
  * Represents a method signature.
@@ -131,7 +135,7 @@
             JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0));
             return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(kind.toJavaClass());
         }
-        return new HotSpotUnresolvedJavaType(name, runtime);
+        return HotSpotUnresolvedJavaType.create(runtime, name);
     }
 
     @Override
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,13 +22,63 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.SpeculationLog;
 
-public class HotSpotSpeculationLog extends SpeculationLog {
+public class HotSpotSpeculationLog implements SpeculationLog {
+
+    /** Written by the C++ code that performs deoptimization. */
+    private volatile Object lastFailed;
+
+    /** All speculations that have been a deoptimization reason. */
+    private Set<SpeculationReason> failedSpeculations;
+
+    /** Strong references to all reasons embededded in the current nmethod. */
+    private volatile Collection<SpeculationReason> speculations;
 
     @Override
-    public JavaConstant speculate(Object reason) {
-        addSpeculation(reason);
+    public synchronized void collectFailedSpeculations() {
+        if (lastFailed != null) {
+            if (failedSpeculations == null) {
+                failedSpeculations = new HashSet<>(2);
+            }
+            failedSpeculations.add((SpeculationReason) lastFailed);
+            lastFailed = null;
+            speculations = null;
+        }
+    }
+
+    @Override
+    public boolean maySpeculate(SpeculationReason reason) {
+        if (failedSpeculations != null && failedSpeculations.contains(reason)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public JavaConstant speculate(SpeculationReason reason) {
+        assert maySpeculate(reason);
+
+        /*
+         * Objects referenced from nmethods are weak references. We need a strong reference to the
+         * reason objects that are embedded in nmethods, so we add them to the speculations
+         * collection.
+         */
+        if (speculations == null) {
+            synchronized (this) {
+                if (speculations == null) {
+                    speculations = new ConcurrentLinkedQueue<>();
+                }
+            }
+        }
+        speculations.add(reason);
+
         return HotSpotObjectConstantImpl.forObject(reason);
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,10 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.util.*;
+import java.util.Arrays;
 
-import jdk.vm.ci.code.stack.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.stack.InspectedFrame;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public class HotSpotStackFrameReference implements InspectedFrame {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackIntrospection.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.hotspot;
+
+import jdk.vm.ci.code.stack.InspectedFrameVisitor;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class HotSpotStackIntrospection implements StackIntrospection {
+
+    protected final HotSpotJVMCIRuntimeProvider runtime;
+
+    public HotSpotStackIntrospection(HotSpotJVMCIRuntimeProvider runtime) {
+        this.runtime = runtime;
+    }
+
+    @Override
+    public <T> T iterateFrames(ResolvedJavaMethod[] initialMethods, ResolvedJavaMethod[] matchingMethods, int initialSkip, InspectedFrameVisitor<T> visitor) {
+        CompilerToVM compilerToVM = runtime.getCompilerToVM();
+        HotSpotStackFrameReference current = compilerToVM.getNextStackFrame(null, initialMethods, initialSkip);
+        while (current != null) {
+            T result = visitor.visitFrame(current);
+            if (result != null) {
+                return result;
+            }
+            current = compilerToVM.getNextStackFrame(current, matchingMethods, 0);
+        }
+        return null;
+    }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,18 +22,19 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaField;
+import jdk.vm.ci.meta.JavaType;
 
 /**
  * A implementation of {@link JavaField} for an unresolved field.
  */
-public class HotSpotUnresolvedField implements JavaField {
+class HotSpotUnresolvedField implements JavaField {
 
     private final String name;
     private final JavaType holder;
     private final JavaType type;
 
-    public HotSpotUnresolvedField(JavaType holder, String name, JavaType type) {
+    HotSpotUnresolvedField(JavaType holder, String name, JavaType type) {
         this.name = name;
         this.type = type;
         this.holder = holder;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,16 +22,18 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * Implementation of {@link JavaType} for unresolved HotSpot classes.
  */
-public class HotSpotUnresolvedJavaType extends HotSpotJavaType {
+final class HotSpotUnresolvedJavaType extends HotSpotJavaType {
 
     private final HotSpotJVMCIRuntimeProvider runtime;
 
-    public HotSpotUnresolvedJavaType(String name, HotSpotJVMCIRuntimeProvider runtime) {
+    private HotSpotUnresolvedJavaType(String name, HotSpotJVMCIRuntimeProvider runtime) {
         super(name);
         assert name.charAt(0) == '[' || name.charAt(name.length() - 1) == ';' : name;
         this.runtime = runtime;
@@ -40,7 +42,7 @@
     /**
      * Creates an unresolved type for a valid {@link JavaType#getName() type name}.
      */
-    public static HotSpotUnresolvedJavaType create(HotSpotJVMCIRuntimeProvider runtime, String name) {
+    static HotSpotUnresolvedJavaType create(HotSpotJVMCIRuntimeProvider runtime, String name) {
         return new HotSpotUnresolvedJavaType(name, runtime);
     }
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Wed Jul 05 21:00:20 2017 +0200
@@ -23,14 +23,23 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.common.UnsafeUtil.readCString;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Iterator;
 
-import sun.misc.*;
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.hotspotvmconfig.*;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspotvmconfig.HotSpotVMAddress;
+import jdk.vm.ci.hotspotvmconfig.HotSpotVMConstant;
+import jdk.vm.ci.hotspotvmconfig.HotSpotVMData;
+import jdk.vm.ci.hotspotvmconfig.HotSpotVMField;
+import jdk.vm.ci.hotspotvmconfig.HotSpotVMFlag;
+import jdk.vm.ci.hotspotvmconfig.HotSpotVMManual;
+import jdk.vm.ci.hotspotvmconfig.HotSpotVMType;
+import sun.misc.Unsafe;
 
 //JaCoCo Exclude
 
@@ -42,13 +51,20 @@
 public class HotSpotVMConfig {
 
     /**
+     * Gets the configuration associated with the singleton {@link HotSpotJVMCIRuntime}.
+     */
+    public static HotSpotVMConfig config() {
+        return runtime().getConfig();
+    }
+
+    /**
      * Maximum allowed size of allocated area for a frame.
      */
     public final int maxFrameSize = 16 * 1024;
 
     public HotSpotVMConfig(CompilerToVM compilerToVm) {
         // Get raw pointer to the array that contains all gHotSpotVM values.
-        final long gHotSpotVMData = compilerToVm.initializeConfiguration();
+        final long gHotSpotVMData = compilerToVm.initializeConfiguration(this);
         assert gHotSpotVMData != 0;
 
         // Make FindBugs happy.
@@ -106,6 +122,8 @@
         handleDeoptStub = deoptBlob + UNSAFE.getInt(deoptBlob + codeBlobCodeOffsetOffset) + UNSAFE.getInt(deoptBlob + deoptimizationBlobUnpackOffsetOffset);
         uncommonTrapStub = deoptBlob + UNSAFE.getInt(deoptBlob + codeBlobCodeOffsetOffset) + UNSAFE.getInt(deoptBlob + deoptimizationBlobUncommonTrapOffsetOffset);
 
+        tlabAlignmentReserve = roundUp(threadLocalAllocBufferEndReserve(), minObjAlignment());
+
         assert check();
         assert HotSpotVMConfigVerifier.check();
     }
@@ -844,6 +862,7 @@
 
     @HotSpotVMConstant(name = "ASSERT") @Stable public boolean cAssertions;
     public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
+    public final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
 
     @HotSpotVMFlag(name = "CodeEntryAlignment") @Stable public int codeEntryAlignment;
     @HotSpotVMFlag(name = "VerifyOops") @Stable public boolean verifyOops;
@@ -938,6 +957,16 @@
     @HotSpotVMConstant(name = "VM_Version::CPU_ERMS", archs = {"amd64"}) @Stable public long cpuERMS;
     @HotSpotVMConstant(name = "VM_Version::CPU_CLMUL", archs = {"amd64"}) @Stable public long cpuCLMUL;
     @HotSpotVMConstant(name = "VM_Version::CPU_BMI1", archs = {"amd64"}) @Stable public long cpuBMI1;
+    @HotSpotVMConstant(name = "VM_Version::CPU_BMI2", archs = {"amd64"}) @Stable public long cpuBMI2;
+    @HotSpotVMConstant(name = "VM_Version::CPU_RTM", archs = {"amd64"}) @Stable public long cpuRTM;
+    @HotSpotVMConstant(name = "VM_Version::CPU_ADX", archs = {"amd64"}) @Stable public long cpuADX;
+    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512F", archs = {"amd64"}) @Stable public long cpuAVX512F;
+    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512DQ", archs = {"amd64"}) @Stable public long cpuAVX512DQ;
+    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512PF", archs = {"amd64"}) @Stable public long cpuAVX512PF;
+    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512ER", archs = {"amd64"}) @Stable public long cpuAVX512ER;
+    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512CD", archs = {"amd64"}) @Stable public long cpuAVX512CD;
+    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512BW", archs = {"amd64"}) @Stable public long cpuAVX512BW;
+    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512VL", archs = {"amd64"}) @Stable public long cpuAVX512VL;
 
     // SPARC specific values
     @HotSpotVMField(name = "VM_Version::_features", type = "int", get = HotSpotVMField.Type.VALUE, archs = {"sparc"}) @Stable public int sparcFeatures;
@@ -945,6 +974,26 @@
     @HotSpotVMConstant(name = "VM_Version::vis2_instructions_m", archs = {"sparc"}) @Stable public int vis2Instructions;
     @HotSpotVMConstant(name = "VM_Version::vis1_instructions_m", archs = {"sparc"}) @Stable public int vis1Instructions;
     @HotSpotVMConstant(name = "VM_Version::cbcond_instructions_m", archs = {"sparc"}) @Stable public int cbcondInstructions;
+    @HotSpotVMConstant(name = "VM_Version::v8_instructions_m", archs = {"sparc"}) @Stable public int v8Instructions;
+    @HotSpotVMConstant(name = "VM_Version::hardware_mul32_m", archs = {"sparc"}) @Stable public int hardwareMul32;
+    @HotSpotVMConstant(name = "VM_Version::hardware_div32_m", archs = {"sparc"}) @Stable public int hardwareDiv32;
+    @HotSpotVMConstant(name = "VM_Version::hardware_fsmuld_m", archs = {"sparc"}) @Stable public int hardwareFsmuld;
+    @HotSpotVMConstant(name = "VM_Version::hardware_popc_m", archs = {"sparc"}) @Stable public int hardwarePopc;
+    @HotSpotVMConstant(name = "VM_Version::v9_instructions_m", archs = {"sparc"}) @Stable public int v9Instructions;
+    @HotSpotVMConstant(name = "VM_Version::sun4v_m", archs = {"sparc"}) @Stable public int sun4v;
+    @HotSpotVMConstant(name = "VM_Version::blk_init_instructions_m", archs = {"sparc"}) @Stable public int blkInitInstructions;
+    @HotSpotVMConstant(name = "VM_Version::fmaf_instructions_m", archs = {"sparc"}) @Stable public int fmafInstructions;
+    @HotSpotVMConstant(name = "VM_Version::fmau_instructions_m", archs = {"sparc"}) @Stable public int fmauInstructions;
+    @HotSpotVMConstant(name = "VM_Version::sparc64_family_m", archs = {"sparc"}) @Stable public int sparc64Family;
+    @HotSpotVMConstant(name = "VM_Version::M_family_m", archs = {"sparc"}) @Stable public int mFamily;
+    @HotSpotVMConstant(name = "VM_Version::T_family_m", archs = {"sparc"}) @Stable public int tFamily;
+    @HotSpotVMConstant(name = "VM_Version::T1_model_m", archs = {"sparc"}) @Stable public int t1Model;
+    @HotSpotVMConstant(name = "VM_Version::sparc5_instructions_m", archs = {"sparc"}) @Stable public int sparc5Instructions;
+    @HotSpotVMConstant(name = "VM_Version::aes_instructions_m", archs = {"sparc"}) @Stable public int aesInstructions;
+    @HotSpotVMConstant(name = "VM_Version::sha1_instruction_m", archs = {"sparc"}) @Stable public int sha1Instruction;
+    @HotSpotVMConstant(name = "VM_Version::sha256_instruction_m", archs = {"sparc"}) @Stable public int sha256Instruction;
+    @HotSpotVMConstant(name = "VM_Version::sha512_instruction_m", archs = {"sparc"}) @Stable public int sha512Instruction;
+
     @HotSpotVMFlag(name = "UseBlockZeroing", archs = {"sparc"}) @Stable public boolean useBlockZeroing;
     @HotSpotVMFlag(name = "BlockZeroingLowLimit", archs = {"sparc"}) @Stable public int blockZeroingLowLimit;
 
@@ -1396,6 +1445,7 @@
     @HotSpotVMField(name = "Thread::_allocated_bytes", type = "jlong", get = HotSpotVMField.Type.OFFSET) @Stable public int threadAllocatedBytesOffset;
 
     @HotSpotVMFlag(name = "TLABWasteIncrement") @Stable public int tlabRefillWasteIncrement;
+    @HotSpotVMManual(name = "ThreadLocalAllocBuffer::alignment_reserve()") @Stable public int tlabAlignmentReserve;
 
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_start", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferStartOffset;
     @HotSpotVMField(name = "ThreadLocalAllocBuffer::_end", type = "HeapWord*", get = HotSpotVMField.Type.OFFSET) @Stable private int threadLocalAllocBufferEndOffset;
@@ -1453,13 +1503,6 @@
         return Integer.max(reserveSize, abstractVmVersionReserveForAllocationPrefetch);
     }
 
-    /**
-     * See: {@code ThreadLocalAllocBuffer::alignment_reserve()}.
-     */
-    public final int tlabAlignmentReserve() {
-        return roundUp(threadLocalAllocBufferEndReserve(), minObjAlignment());
-    }
-
     @HotSpotVMFlag(name = "TLABStats") @Stable public boolean tlabStats;
 
     // FIXME This is only temporary until the GC code is changed.
@@ -1688,6 +1731,7 @@
     @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_NEAR") @Stable public int MARKID_POLL_RETURN_NEAR;
     @HotSpotVMConstant(name = "CodeInstaller::POLL_FAR") @Stable public int MARKID_POLL_FAR;
     @HotSpotVMConstant(name = "CodeInstaller::POLL_RETURN_FAR") @Stable public int MARKID_POLL_RETURN_FAR;
+    @HotSpotVMConstant(name = "CodeInstaller::CARD_TABLE_SHIFT") @Stable public int MARKID_CARD_TABLE_SHIFT;
     @HotSpotVMConstant(name = "CodeInstaller::CARD_TABLE_ADDRESS") @Stable public int MARKID_CARD_TABLE_ADDRESS;
     @HotSpotVMConstant(name = "CodeInstaller::HEAP_TOP_ADDRESS") @Stable public int MARKID_HEAP_TOP_ADDRESS;
     @HotSpotVMConstant(name = "CodeInstaller::HEAP_END_ADDRESS") @Stable public int MARKID_HEAP_END_ADDRESS;
@@ -1695,6 +1739,20 @@
     @HotSpotVMConstant(name = "CodeInstaller::CRC_TABLE_ADDRESS") @Stable public int MARKID_CRC_TABLE_ADDRESS;
     @HotSpotVMConstant(name = "CodeInstaller::INVOKE_INVALID") @Stable public int MARKID_INVOKE_INVALID;
 
+    @HotSpotVMConstant(name = "BitData::exception_seen_flag") @Stable public int bitDataExceptionSeenFlag;
+    @HotSpotVMConstant(name = "BitData::null_seen_flag") @Stable public int bitDataNullSeenFlag;
+    @HotSpotVMConstant(name = "CounterData::count_off") @Stable public int methodDataCountOffset;
+    @HotSpotVMConstant(name = "JumpData::taken_off_set") @Stable public int jumpDataTakenOffset;
+    @HotSpotVMConstant(name = "JumpData::displacement_off_set") @Stable public int jumpDataDisplacementOffset;
+    @HotSpotVMConstant(name = "ReceiverTypeData::nonprofiled_count_off_set") @Stable public int receiverTypeDataNonprofiledCountOffset;
+    @HotSpotVMConstant(name = "ReceiverTypeData::receiver_type_row_cell_count") @Stable public int receiverTypeDataReceiverTypeRowCellCount;
+    @HotSpotVMConstant(name = "ReceiverTypeData::receiver0_offset") @Stable public int receiverTypeDataReceiver0Offset;
+    @HotSpotVMConstant(name = "ReceiverTypeData::count0_offset") @Stable public int receiverTypeDataCount0Offset;
+    @HotSpotVMConstant(name = "BranchData::not_taken_off_set") @Stable public int branchDataNotTakenOffset;
+    @HotSpotVMConstant(name = "ArrayData::array_len_off_set") @Stable public int arrayDataArrayLenOffset;
+    @HotSpotVMConstant(name = "ArrayData::array_start_off_set") @Stable public int arrayDataArrayStartOffset;
+    @HotSpotVMConstant(name = "MultiBranchData::per_case_cell_count") @Stable public int multiBranchDataPerCaseCellCount;
+
     // Checkstyle: resume
 
     private boolean check() {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,16 +22,25 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static java.lang.String.*;
+import static java.lang.String.format;
 
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Objects;
 
-import jdk.internal.org.objectweb.asm.*;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.vm.ci.common.*;
-import sun.misc.*;
+import sun.misc.Unsafe;
 
 /**
  * A {@link ClassVisitor} that verifies {@link HotSpotVMConfig} does not access {@link Unsafe} from
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,8 +22,10 @@
  */
 package jdk.vm.ci.hotspot;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.JVMCIMetaAccessContext;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 public interface HotSpotVMEventListener {
 
@@ -34,7 +36,7 @@
     }
 
     /**
-     * Notify on successful install into the CodeCache.
+     * Notify on successful install into the code cache.
      *
      * @param hotSpotCodeCacheProvider
      * @param installedCode
@@ -44,14 +46,6 @@
     }
 
     /**
-     * Perform any extra initialization required.
-     *
-     * @param runtime
-     */
-    default void completeInitialization(HotSpotJVMCIRuntime runtime) {
-    }
-
-    /**
      * Create a custom {@link JVMCIMetaAccessContext} to be used for managing the lifetime of loaded
      * metadata. It a custom one isn't created then the default implementation will be a single
      * context with globally shared instances of {@link ResolvedJavaType} that are never released.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,15 +22,14 @@
  */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
-
-import sun.misc.*;
+import sun.misc.Unsafe;
 
 /**
  * Class to access the C++ {@code vmSymbols} table.
  */
-public final class HotSpotVmSymbols {
+final class HotSpotVmSymbols {
 
     /**
      * Returns the symbol in the {@code vmSymbols} table at position {@code index} as {@link String}
@@ -39,7 +38,7 @@
      * @param index position in the symbol table
      * @return the symbol at position id
      */
-    public static String symbolAt(int index) {
+    static String symbolAt(int index) {
         HotSpotJVMCIRuntimeProvider runtime = runtime();
         HotSpotVMConfig config = runtime.getConfig();
         assert config.vmSymbolsFirstSID <= index && index < config.vmSymbolsSIDLimit : "index " + index + " is out of bounds";
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  * It would preferable if this were the base class containing the pointer but that would require
  * mixins since most of the wrapper types have complex supertype hierarchies.
  */
-public interface MetaspaceWrapperObject {
+interface MetaspaceWrapperObject {
 
     long getMetaspacePointer();
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java	Wed Jul 05 21:00:20 2017 +0200
@@ -23,11 +23,14 @@
 
 package jdk.vm.ci.hotspot;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
- * This annotation functions as an alias for the sun.invoke.Stable annotation within JVMCI code. It
- * is specially recognized during class file parsing in the same way as that annotation.
+ * This annotation functions as an alias for the java.lang.invoke.Stable annotation within JVMCI
+ * code. It is specially recognized during class file parsing in the same way as that annotation.
  */
 @Target(ElementType.FIELD)
 @Retention(RetentionPolicy.RUNTIME)
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/SuppressFBWarnings.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * 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 jdk.vm.ci.hotspot;
-
-/**
- * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
- */
-public @interface SuppressFBWarnings {
-    /**
-     * The set of FindBugs <a
-     * href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
-     * suppressed in annotated element. The value can be a bug category, kind or pattern.
-     */
-    String[] value();
-
-    /**
-     * Reason why the warning is suppressed.
-     */
-    String justification();
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EmptyEventProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EmptyEventProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.hotspot.events;
 
-import jdk.vm.ci.common.*;
+import jdk.vm.ci.common.JVMCIError;
 
 /**
  * An empty implementation for {@link EventProvider}. This implementation is used when no logging is
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.hotspotvmconfig;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Refers to a C++ address in the VM.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.hotspotvmconfig;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Refers to a C++ constant in the VM.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.hotspotvmconfig;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Refers to a entry in {@code gHotSpotVMData}.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.hotspotvmconfig;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Refers to a C++ field in the VM.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.hotspotvmconfig;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Refers to a C++ flag in the VM.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMManual.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMManual.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.hotspotvmconfig;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Annotates a field in HotSpotVMConfig which is not read from the VM but is calculated manually.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.hotspotvmconfig;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Refers to a C++ type in the VM.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,8 +22,12 @@
  */
 package jdk.vm.ci.meta;
 
-import java.lang.invoke.*;
-import java.util.*;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
 
 /**
  * Class for recording assumptions made during compilation.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
 
 /**
  * Reflection operations on values represented as {@linkplain JavaConstant constants}. All methods
@@ -142,8 +142,12 @@
 
     /**
      * Check if the constant is embeddable in the code.
+     *
+     * @param constant the constant to test
      */
-    boolean isEmbeddable(Constant constant);
+    default boolean isEmbeddable(Constant constant) {
+        return true;
+    }
 
     /**
      * Gets access to the internals of {@link MethodHandle}.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java	Wed Jul 05 21:00:20 2017 +0200
@@ -93,7 +93,7 @@
 
     @Override
     public String toString() {
-        return "BaseProfilingInfo<" + this.toString(null, "; ") + ">";
+        return "DefaultProfilingInfo<" + this.toString(null, "; ") + ">";
     }
 
     public void setMature() {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import java.util.*;
+import java.util.Objects;
 
 /**
  * Represents an exception handler within the bytecodes.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JVMCIMetaAccessContext.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JVMCIMetaAccessContext.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,8 @@
  */
 package jdk.vm.ci.meta;
 
-import java.util.*;
+import java.util.IllegalFormatException;
+import java.util.UnknownFormatConversionException;
 
 /**
  * Represents a reference to a Java field, either resolved or unresolved fields. Fields, like
@@ -77,7 +78,6 @@
      * @return the result of formatting this field according to {@code format}
      * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
      */
-    @SuppressWarnings("fallthrough")
     default String format(String format) throws IllegalFormatException {
         StringBuilder sb = new StringBuilder();
         int index = 0;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import java.lang.reflect.*;
+import java.lang.reflect.Array;
 
 //JaCoCo Exclude
 
@@ -31,7 +31,7 @@
  * {@link JavaKind#Int} for {@code int} and {@link JavaKind#Object} for all object types. A kind has
  * a single character short name, a Java name, and a set of flags further describing its behavior.
  */
-public enum JavaKind implements PlatformKind {
+public enum JavaKind {
     /** The primitive boolean kind, represented as an int on the stack. */
     Boolean('z', "boolean", 1, true, java.lang.Boolean.TYPE, java.lang.Boolean.class),
 
@@ -70,7 +70,6 @@
     private final boolean isStackInt;
     private final Class<?> primitiveJavaClass;
     private final Class<?> boxedJavaClass;
-    private final EnumKey<JavaKind> key = new EnumKey<>(this);
     private final int slotCount;
 
     private JavaKind(char typeChar, String javaName, int slotCount, boolean isStackInt, Class<?> primitiveJavaClass, Class<?> boxedJavaClass) {
@@ -113,10 +112,6 @@
         return javaName;
     }
 
-    public Key getKey() {
-        return key;
-    }
-
     /**
      * Checks whether this type is a Java primitive type.
      *
@@ -460,37 +455,4 @@
                 throw new IllegalArgumentException("illegal call to bits on " + this);
         }
     }
-
-    public JavaConstant getDefaultValue() {
-        switch (this) {
-            case Boolean:
-                return JavaConstant.FALSE;
-            case Int:
-                return JavaConstant.INT_0;
-            case Long:
-                return JavaConstant.LONG_0;
-            case Float:
-                return JavaConstant.FLOAT_0;
-            case Double:
-                return JavaConstant.DOUBLE_0;
-            case Object:
-                return JavaConstant.NULL_POINTER;
-            case Byte:
-            case Char:
-            case Short:
-                return new PrimitiveConstant(this, 0);
-            default:
-                throw new IllegalArgumentException("illegal call to getDefaultValue on " + this);
-        }
-    }
-
-    @Override
-    public int getSizeInBytes() {
-        return getByteCount();
-    }
-
-    @Override
-    public int getVectorLength() {
-        return 1;
-    }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,8 @@
  */
 package jdk.vm.ci.meta;
 
-import java.util.*;
+import java.util.IllegalFormatException;
+import java.util.UnknownFormatConversionException;
 
 /**
  * Represents a reference to a Java method, either resolved or unresolved. Methods, like fields and
@@ -71,7 +72,6 @@
      * @return the result of formatting this method according to {@code format}
      * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
      */
-    @SuppressWarnings("fallthrough")
     default String format(String format) throws IllegalFormatException {
         StringBuilder sb = new StringBuilder();
         int index = 0;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import jdk.vm.ci.meta.JavaMethodProfile.*;
+import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod;
 
 /**
  * This profile object represents the method profile at a specific BCI. The precision of the
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import static jdk.vm.ci.meta.MetaUtil.*;
+import static jdk.vm.ci.meta.MetaUtil.internalNameToJava;
 
 /**
  * Represents a resolved or unresolved type. Types include primitives, objects, {@code void}, and
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,9 @@
  */
 package jdk.vm.ci.meta;
 
-import java.util.*;
+import java.util.ArrayList;
 
-import jdk.vm.ci.meta.JavaTypeProfile.*;
+import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
 
 /**
  * This profile object represents the type profile at a specific BCI. The precision of the supplied
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import java.util.*;
+import java.util.ArrayList;
 
 /**
  * Represents the type of values in the LIR. It is composed of a {@link PlatformKind} that gives the
@@ -57,10 +57,32 @@
  */
 public final class LIRKind {
 
+    private static enum IllegalKind implements PlatformKind {
+        ILLEGAL;
+
+        private final EnumKey<IllegalKind> key = new EnumKey<>(this);
+
+        public Key getKey() {
+            return key;
+        }
+
+        public int getSizeInBytes() {
+            return 0;
+        }
+
+        public int getVectorLength() {
+            return 0;
+        }
+
+        public char getTypeChar() {
+            return '-';
+        }
+    }
+
     /**
      * The non-type. This uses {@link #unknownReference}, so it can never be part of an oop map.
      */
-    public static final LIRKind Illegal = unknownReference(JavaKind.Illegal);
+    public static final LIRKind Illegal = unknownReference(IllegalKind.ILLEGAL);
 
     private final PlatformKind platformKind;
     private final int referenceMask;
@@ -70,7 +92,6 @@
     private static final int UNKNOWN_REFERENCE = -1;
 
     private LIRKind(PlatformKind platformKind, int referenceMask, AllocatableValue derivedReferenceBase) {
-        assert platformKind != JavaKind.Object : "Kind.Object shouldn't be used in the backend";
         this.platformKind = platformKind;
         this.referenceMask = referenceMask;
         this.derivedReferenceBase = derivedReferenceBase;
@@ -431,21 +452,9 @@
         if (src.equals(dst)) {
             return true;
         }
-        /*
-         * TODO(je,rs) What we actually want is toStackKind(src.getPlatformKind()).equals(
-         * dst.getPlatformKind()) but due to the handling of sub-integer at the current point
-         * (phi-)moves from e.g. integer to short can happen. Therefore we compare stack kinds.
-         */
-        if (toStackKind(src.getPlatformKind()).equals(toStackKind(dst.getPlatformKind()))) {
+        if (src.getPlatformKind().equals(dst.getPlatformKind())) {
             return !src.isUnknownReference() || dst.isUnknownReference();
         }
         return false;
     }
-
-    private static PlatformKind toStackKind(PlatformKind platformKind) {
-        if (platformKind instanceof JavaKind) {
-            return ((JavaKind) platformKind).getStackKind();
-        }
-        return platformKind;
-    }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTableImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTableImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,8 @@
  */
 package jdk.vm.ci.meta;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
 
 public class LocalVariableTableImpl implements LocalVariableTable {
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocationIdentity.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocationIdentity.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import java.util.*;
+import java.util.IdentityHashMap;
 
 // JaCoCo Exclude
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.meta;
 
-import java.lang.reflect.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 
 /**
  * Provides access to the metadata of a class typically provided in a class file.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,17 @@
  */
 package jdk.vm.ci.meta;
 
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
 
 /**
  * Interface to access the internals of the {@link MethodHandle} implementation of the VM. An
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,20 @@
  */
 package jdk.vm.ci.meta;
 
-import static java.lang.reflect.Modifier.*;
+import static java.lang.reflect.Modifier.ABSTRACT;
+import static java.lang.reflect.Modifier.FINAL;
+import static java.lang.reflect.Modifier.INTERFACE;
+import static java.lang.reflect.Modifier.NATIVE;
+import static java.lang.reflect.Modifier.PRIVATE;
+import static java.lang.reflect.Modifier.PROTECTED;
+import static java.lang.reflect.Modifier.PUBLIC;
+import static java.lang.reflect.Modifier.STATIC;
+import static java.lang.reflect.Modifier.STRICT;
+import static java.lang.reflect.Modifier.SYNCHRONIZED;
+import static java.lang.reflect.Modifier.TRANSIENT;
+import static java.lang.reflect.Modifier.VOLATILE;
 
-import java.lang.reflect.*;
+import java.lang.reflect.Modifier;
 
 /**
  * A Java element (i.e., a class, interface, field or method) that is described by a set of Java
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,8 +29,6 @@
 
     String name();
 
-    JavaConstant getDefaultValue();
-
     public interface Key {
 
     }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import java.nio.*;
+import java.nio.ByteBuffer;
 
 /**
  * Represents a primitive constant value, such as an integer or floating point number, within the
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,8 +22,8 @@
  */
 package jdk.vm.ci.meta;
 
-import java.lang.annotation.*;
-import java.lang.reflect.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Modifier;
 
 /**
  * Represents a reference to a resolved Java field. Fields, like methods and types, are resolved
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,12 @@
  */
 package jdk.vm.ci.meta;
 
-import java.lang.annotation.*;
-import java.lang.invoke.*;
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.annotation.Annotation;
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
 
 /**
  * Represents a resolved Java method. Methods, like fields and types, are resolved through
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,10 @@
  */
 package jdk.vm.ci.meta;
 
-import java.lang.annotation.*;
-import java.net.*;
+import java.lang.annotation.Annotation;
+import java.net.URL;
 
-import jdk.vm.ci.meta.Assumptions.*;
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
 
 /**
  * Represents a resolved Java type. Types include primitives, objects, {@code void}, and arrays
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.meta;
 
-import java.nio.*;
+import java.nio.ByteBuffer;
 
 /**
  * Represents a compile-time constant that can be converted to a byte array.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,47 +22,38 @@
  */
 package jdk.vm.ci.meta;
 
-import java.util.*;
-import java.util.concurrent.*;
-
 /**
- * Manages a list of unique deoptimization reasons.
+ * Manages unique deoptimization reasons. Reasons are embedded in compiled code and can be
+ * invalidated at run time. Subsequent compilations then should not speculate again on such
+ * invalidated reasons to avoid repeated deoptimization.
  *
+ * All methods of this interface are called by the compiler. There is no need for API to register
+ * failed speculations during deoptimization, since every VM has different needs there.
  */
-public abstract class SpeculationLog {
-    private volatile Object lastFailed;
-    private volatile Collection<Object> speculations;
-    private Set<Object> failedSpeculations;
+public interface SpeculationLog {
 
-    public synchronized void collectFailedSpeculations() {
-        if (lastFailed != null) {
-            if (failedSpeculations == null) {
-                failedSpeculations = new HashSet<>(2);
-            }
-            failedSpeculations.add(lastFailed);
-            lastFailed = null;
-            speculations = null;
-        }
+    /**
+     * Marker interface for speculation objects that can be added to the speculation log.
+     */
+    public interface SpeculationReason {
     }
 
-    public boolean maySpeculate(Object reason) {
-        if (failedSpeculations != null && failedSpeculations.contains(reason)) {
-            return false;
-        }
-        return true;
-    }
+    /**
+     * Must be called before compilation, i.e., before a compiler calls {@link #maySpeculate}.
+     */
+    void collectFailedSpeculations();
 
-    protected void addSpeculation(Object reason) {
-        assert maySpeculate(reason);
-        if (speculations == null) {
-            synchronized (this) {
-                if (speculations == null) {
-                    speculations = new ConcurrentLinkedQueue<>();
-                }
-            }
-        }
-        speculations.add(reason);
-    }
+    /**
+     * If this method returns true, the compiler is allowed to {@link #speculate} with the given
+     * reason.
+     */
+    boolean maySpeculate(SpeculationReason reason);
 
-    public abstract JavaConstant speculate(Object reason);
+    /**
+     * Registers a speculation that was performed by the compiler.
+     *
+     * @return A compiler constant encapsulating the provided reason. It is usually passed as an
+     *         argument to the deoptimization function.
+     */
+    JavaConstant speculate(SpeculationReason reason);
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/jdk/vm/ci/options/processor/OptionProcessor.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/jdk/vm/ci/options/processor/OptionProcessor.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,19 +22,40 @@
  */
 package jdk.vm.ci.options.processor;
 
-import java.io.*;
-import java.util.*;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
-import javax.annotation.processing.*;
-import javax.lang.model.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
-import javax.lang.model.util.*;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
 import javax.tools.Diagnostic.Kind;
+import javax.tools.JavaFileObject;
 
-import jdk.vm.ci.options.*;
-
-import javax.tools.*;
+import jdk.vm.ci.options.Option;
+import jdk.vm.ci.options.OptionDescriptor;
+import jdk.vm.ci.options.OptionDescriptors;
+import jdk.vm.ci.options.OptionValue;
 
 /**
  * Processes static fields annotated with {@link Option}. An {@link OptionDescriptors}
@@ -105,11 +126,11 @@
         DeclaredType declaredOptionValueType = declaredFieldType;
         while (!types.isSameType(types.erasure(declaredOptionValueType), types.erasure(optionValueType))) {
             List<? extends TypeMirror> directSupertypes = types.directSupertypes(declaredFieldType);
-            assert!directSupertypes.isEmpty();
+            assert !directSupertypes.isEmpty();
             declaredOptionValueType = (DeclaredType) directSupertypes.get(0);
         }
 
-        assert!declaredOptionValueType.getTypeArguments().isEmpty();
+        assert !declaredOptionValueType.getTypeArguments().isEmpty();
         String optionType = declaredOptionValueType.getTypeArguments().get(0).toString();
         if (optionType.startsWith("java.lang.")) {
             optionType = optionType.substring("java.lang.".length());
@@ -194,8 +215,7 @@
                 if (info.options.size() == 1) {
                     out.printf("            return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
                 } else {
-                    out.printf("            case \"" + name + "\": return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName,
-                                    optionValue);
+                    out.printf("            case \"" + name + "\": return %s.create(\"%s\", %s.class, \"%s\", %s.class, \"%s\", %s);\n", desc, name, type, help, declaringClass, fieldName, optionValue);
                 }
             }
             out.println("        }");
@@ -241,19 +261,6 @@
             }
             out.println("}");
         }
-
-        try {
-            createOptionsFile(pkg, topDeclaringClass.toString(), originatingElements);
-        } catch (IOException e) {
-            processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType);
-        }
-    }
-
-    private void createOptionsFile(String pkg, String relativeName, Element... originatingElements) throws IOException {
-        String filename = "META-INF/jvmci.options/" + pkg + "." + relativeName;
-        FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements);
-        PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8"));
-        writer.close();
     }
 
     protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/DerivedOptionValue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/DerivedOptionValue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,10 @@
  */
 package jdk.vm.ci.options;
 
-import java.io.*;
-import java.util.function.*;
+import java.io.Serializable;
+import java.util.function.Supplier;
 
-import jdk.vm.ci.options.OptionValue.*;
+import jdk.vm.ci.options.OptionValue.OverrideScope;
 
 /**
  * A cached value that needs to be recomputed when an option changes.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/JVMCIJarsOptionDescriptorsProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.vm.ci.options;
-
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.zip.*;
-
-import jdk.vm.ci.options.OptionsParser.*;
-
-/**
- * Access to the {@link OptionDescriptors} declared by
- * {@code META-INF/services/jdk.vm.ci.options.OptionDescriptors} files in {@code
- * <jre>/lib/jvmci/*.jar}.
- */
-class JVMCIJarsOptionDescriptorsProvider implements OptionDescriptorsProvider {
-
-    static final String OptionDescriptorsServiceFile = "META-INF/services/" + OptionDescriptors.class.getName();
-
-    private final Iterator<File> jars;
-    private final List<OptionDescriptors> optionsDescriptorsList;
-
-    JVMCIJarsOptionDescriptorsProvider() {
-        List<File> jarsList = findJVMCIJars();
-        this.jars = jarsList.iterator();
-        this.optionsDescriptorsList = new ArrayList<>(jarsList.size() * 3);
-    }
-
-    /**
-     * Finds the list of JVMCI jars.
-     */
-    private static List<File> findJVMCIJars() {
-        File javaHome = new File(System.getProperty("java.home"));
-        File lib = new File(javaHome, "lib");
-        File jvmci = new File(lib, "jvmci");
-
-        List<File> jarFiles = new ArrayList<>();
-        if (jvmci.exists()) {
-            for (String fileName : jvmci.list()) {
-                if (fileName.endsWith(".jar")) {
-                    File file = new File(jvmci, fileName);
-                    if (file.isDirectory()) {
-                        continue;
-                    }
-                    jarFiles.add(file);
-                }
-            }
-        }
-        return jarFiles;
-    }
-
-    public OptionDescriptor get(String name) {
-        // Look up loaded option descriptors first
-        for (OptionDescriptors optionDescriptors : optionsDescriptorsList) {
-            OptionDescriptor desc = optionDescriptors.get(name);
-            if (desc != null) {
-                return desc;
-            }
-        }
-        while (jars.hasNext()) {
-            File path = jars.next();
-            try (JarFile jar = new JarFile(path)) {
-                ZipEntry entry = jar.getEntry(OptionDescriptorsServiceFile);
-                if (entry != null) {
-                    BufferedReader br = new BufferedReader(new InputStreamReader(jar.getInputStream(entry)));
-                    String line = null;
-                    OptionDescriptor desc = null;
-                    while ((line = br.readLine()) != null) {
-                        OptionDescriptors options;
-                        try {
-                            options = (OptionDescriptors) Class.forName(line).newInstance();
-                            optionsDescriptorsList.add(options);
-                            if (desc == null) {
-                                desc = options.get(name);
-                            }
-                        } catch (Exception e) {
-                            throw new InternalError("Error instantiating class " + line + " read from " + path, e);
-                        }
-                    }
-                    if (desc != null) {
-                        return desc;
-                    }
-                }
-            } catch (IOException e) {
-                throw new InternalError("Error reading " + path, e);
-            }
-        }
-        return null;
-    }
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/NestedBooleanOptionValue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/NestedBooleanOptionValue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/Option.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/Option.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.options;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Describes the attributes of an option whose {@link OptionValue value} is in a static field
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionValue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionValue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,9 +22,15 @@
  */
 package jdk.vm.ci.options;
 
-import java.io.*;
-import java.util.*;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 
 /**
  * An option value.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsLoader.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsLoader.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,9 @@
  */
 package jdk.vm.ci.options;
 
-import java.util.*;
+import java.util.ServiceLoader;
+import java.util.SortedMap;
+import java.util.TreeMap;
 
 /**
  * Helper class used to load option descriptors. Only to be used in the slow-path.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,21 +22,33 @@
  */
 package jdk.vm.ci.options;
 
-import static jdk.vm.ci.inittimer.InitTimer.*;
+import static jdk.vm.ci.inittimer.InitTimer.timer;
 
-import java.io.*;
-import java.util.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.SortedMap;
 
-import jdk.vm.ci.inittimer.*;
+import jdk.vm.ci.inittimer.InitTimer;
 
 /**
  * This class contains methods for parsing JVMCI options and matching them against a set of
- * {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded from JVMCI jars, either
- * {@linkplain JVMCIJarsOptionDescriptorsProvider directly} or via a {@link ServiceLoader}.
+ * {@link OptionDescriptors}. The {@link OptionDescriptors} are loaded via a {@link ServiceLoader}.
  */
 public class OptionsParser {
 
     private static final OptionValue<Boolean> PrintFlags = new OptionValue<>(false);
+    private static final OptionValue<Boolean> ShowFlags = new OptionValue<>(false);
 
     /**
      * A service for looking up {@link OptionDescriptor}s.
@@ -54,7 +66,7 @@
     }
 
     /**
-     * Parses the options in {@code <jre>/lib/jvmci/options} if {@code parseOptionsFile == true} and
+     * Parses the options in {@code <jdk>/lib/jvmci.options} if {@code parseOptionsFile == true} and
      * the file exists followed by the JVMCI options in {@code options} if {@code options != null}.
      *
      * Called from VM. This method has an object return type to allow it to be called with a VM
@@ -62,87 +74,158 @@
      *
      * @param options JVMCI options as serialized (name, value) pairs
      * @param parseOptionsFile specifies whether to look for and parse
-     *            {@code <jre>/lib/jvmci/options}
+     *            {@code <jdk>/lib/jvmci.options}
      */
     @SuppressWarnings("try")
     public static Boolean parseOptionsFromVM(String[] options, boolean parseOptionsFile) {
+
         try (InitTimer t = timer("ParseOptions")) {
-            JVMCIJarsOptionDescriptorsProvider odp = new JVMCIJarsOptionDescriptorsProvider();
 
             if (parseOptionsFile) {
                 File javaHome = new File(System.getProperty("java.home"));
                 File lib = new File(javaHome, "lib");
-                File jvmci = new File(lib, "jvmci");
-                File jvmciOptions = new File(jvmci, "options");
+                File jvmciOptions = new File(lib, "jvmci.options");
                 if (jvmciOptions.exists()) {
                     try (BufferedReader br = new BufferedReader(new FileReader(jvmciOptions))) {
                         String optionSetting = null;
                         int lineNo = 1;
+                        List<String> optionSettings = new ArrayList<>();
                         while ((optionSetting = br.readLine()) != null) {
                             if (!optionSetting.isEmpty() && optionSetting.charAt(0) != '#') {
                                 try {
-                                    parseOptionSetting(optionSetting, null, odp);
+                                    parseOptionSettingTo(optionSetting, optionSettings);
                                 } catch (Throwable e) {
                                     throw new InternalError("Error parsing " + jvmciOptions + ", line " + lineNo, e);
                                 }
                             }
                             lineNo++;
                         }
+                        try {
+                            parseOptions(optionSettings.toArray(new String[optionSettings.size()]), null, null, null);
+                        } catch (Throwable e) {
+                            throw new InternalError("Error parsing an option from " + jvmciOptions, e);
+                        }
                     } catch (IOException e) {
                         throw new InternalError("Error reading " + jvmciOptions, e);
                     }
                 }
             }
 
-            if (options != null) {
-                assert options.length % 2 == 0;
-                for (int i = 0; i < options.length / 2; i++) {
-                    String name = options[i * 2];
-                    String value = options[i * 2 + 1];
-                    parseOption(OptionsLoader.options, name, value, null, odp);
-                }
-            }
+            parseOptions(options, null, null, null);
         }
         return Boolean.TRUE;
     }
 
     /**
-     * Parses a given option setting.
+     * Parses an ordered list of (name, value) pairs assigning values to JVMCI options.
+     *
+     * @param optionSettings JVMCI options as serialized (name, value) pairs
+     * @param setter the object to notify of the parsed option and value
+     * @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s
+     * @param options the options database to use if {@code odp == null}. If
+     *            {@code options == null && odp == null}, {@link OptionsLoader#options} is used.
+     * @throws IllegalArgumentException if there's a problem parsing {@code option}
+     */
+    public static void parseOptions(String[] optionSettings, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
+        if (optionSettings != null && optionSettings.length != 0) {
+            assert optionSettings.length % 2 == 0;
+
+            moveHelpFlagsToTail(optionSettings);
+
+            for (int i = 0; i < optionSettings.length / 2; i++) {
+                String name = optionSettings[i * 2];
+                String value = optionSettings[i * 2 + 1];
+                parseOption(name, value, setter, odp, options);
+            }
+            if (PrintFlags.getValue() || ShowFlags.getValue()) {
+                Set<String> explicitlyAssigned = new HashSet<>(optionSettings.length / 2);
+                for (int i = 0; i < optionSettings.length / 2; i++) {
+                    String name = optionSettings[i * 2];
+                    explicitlyAssigned.add(name);
+                }
+                printFlags(resolveOptions(options), "JVMCI", System.out, explicitlyAssigned);
+                if (PrintFlags.getValue()) {
+                    System.exit(0);
+                }
+            }
+        }
+    }
+
+    /**
+     * Moves all {@code PrintFlags} and {@code ShowFlags} option settings to the back of
+     * {@code optionSettings}. This allows the help message to show which options had their value
+     * explicitly set (even if to their default value).
+     */
+    private static void moveHelpFlagsToTail(String[] optionSettings) {
+        List<String> tail = null;
+        int insert = 0;
+        for (int i = 0; i < optionSettings.length / 2; i++) {
+            String name = optionSettings[i * 2];
+            String value = optionSettings[i * 2 + 1];
+            if (name.equals("ShowFlags") || name.equals("PrintFlags")) {
+                if (tail == null) {
+                    tail = new ArrayList<>(4);
+                    insert = i * 2;
+                }
+                tail.add(name);
+                tail.add(value);
+            } else if (tail != null) {
+                optionSettings[insert++] = name;
+                optionSettings[insert++] = value;
+            }
+        }
+        if (tail != null) {
+            assert tail.size() + insert == optionSettings.length;
+            String[] tailArr = tail.toArray(new String[tail.size()]);
+            System.arraycopy(tailArr, 0, optionSettings, insert, tailArr.length);
+        }
+    }
+
+    /**
+     * Parses a given option setting string to a list of (name, value) pairs.
      *
      * @param optionSetting a string matching the pattern {@code <name>=<value>}
-     * @param setter the object to notify of the parsed option and value
      */
-    public static void parseOptionSetting(String optionSetting, OptionConsumer setter, OptionDescriptorsProvider odp) {
+    public static void parseOptionSettingTo(String optionSetting, List<String> dst) {
         int eqIndex = optionSetting.indexOf('=');
         if (eqIndex == -1) {
             throw new InternalError("Option setting has does not match the pattern <name>=<value>: " + optionSetting);
         }
-        String name = optionSetting.substring(0, eqIndex);
-        String value = optionSetting.substring(eqIndex + 1);
-        parseOption(OptionsLoader.options, name, value, setter, odp);
+        dst.add(optionSetting.substring(0, eqIndex));
+        dst.add(optionSetting.substring(eqIndex + 1));
+    }
+
+    /**
+     * Resolves {@code options} to a non-null value. This ensures {@link OptionsLoader#options} is
+     * only loaded if necessary.
+     */
+    private static SortedMap<String, OptionDescriptor> resolveOptions(SortedMap<String, OptionDescriptor> options) {
+        return options != null ? options : OptionsLoader.options;
     }
 
     /**
      * Parses a given option name and value.
      *
-     * @param options
      * @param name the option name
      * @param valueString the option value as a string
      * @param setter the object to notify of the parsed option and value
-     * @param odp
-     *
+     * @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s
+     * @param options the options database to use if {@code odp == null}. If
+     *            {@code options == null && odp == null}, {@link OptionsLoader#options} is used.
      * @throws IllegalArgumentException if there's a problem parsing {@code option}
      */
-    public static void parseOption(SortedMap<String, OptionDescriptor> options, String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp) {
-        OptionDescriptor desc = options.get(name);
-        if (desc == null && odp != null) {
-            desc = odp.get(name);
-        }
-        if (desc == null && name.equals("PrintFlags")) {
-            desc = OptionDescriptor.create("PrintFlags", Boolean.class, "Prints all JVMCI flags and exits", OptionsParser.class, "PrintFlags", PrintFlags);
+    private static void parseOption(String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
+
+        OptionDescriptor desc = odp != null ? odp.get(name) : resolveOptions(options).get(name);
+        if (desc == null) {
+            if (name.equals("PrintFlags")) {
+                desc = OptionDescriptor.create("PrintFlags", Boolean.class, "Prints all JVMCI flags and exits", OptionsParser.class, "PrintFlags", PrintFlags);
+            } else if (name.equals("ShowFlags")) {
+                desc = OptionDescriptor.create("ShowFlags", Boolean.class, "Prints all JVMCI flags and continues", OptionsParser.class, "ShowFlags", ShowFlags);
+            }
         }
         if (desc == null) {
-            List<OptionDescriptor> matches = fuzzyMatch(options, name);
+            List<OptionDescriptor> matches = fuzzyMatch(resolveOptions(options), name);
             Formatter msg = new Formatter();
             msg.format("Could not find option %s", name);
             if (!matches.isEmpty()) {
@@ -182,11 +265,6 @@
         } else {
             setter.set(desc, value);
         }
-
-        if (PrintFlags.getValue()) {
-            printFlags(options, "JVMCI", System.out);
-            System.exit(0);
-        }
     }
 
     private static long parseLong(String v) {
@@ -252,16 +330,18 @@
         return lines;
     }
 
-    public static void printFlags(SortedMap<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out) {
+    private static void printFlags(SortedMap<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out, Set<String> explicitlyAssigned) {
         out.println("[List of " + prefix + " options]");
         for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
             e.getKey();
             OptionDescriptor desc = e.getValue();
             Object value = desc.getOptionValue().getValue();
             List<String> helpLines = wrap(desc.getHelp(), 70);
-            out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
+            String name = e.getKey();
+            String assign = explicitlyAssigned.contains(name) ? ":=" : " =";
+            out.printf("%9s %-40s %s %-14s %s%n", desc.getType().getSimpleName(), name, assign, value, helpLines.get(0));
             for (int i = 1; i < helpLines.size(); i++) {
-                out.println(String.format("%67s %s", " ", helpLines.get(i)));
+                out.printf("%67s %s%n", " ", helpLines.get(i));
             }
         }
     }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.runtime;
 
-import java.util.*;
+import java.util.Formatter;
 
 public class JVMCI {
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,8 +22,11 @@
  */
 package jdk.vm.ci.runtime;
 
-import jdk.vm.ci.code.*;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.stack.StackIntrospection;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
 
 /**
  * A JVMCI backend encapsulates the capabilities needed by a Java based compiler for compiling and
@@ -35,11 +38,13 @@
     private final MetaAccessProvider metaAccess;
     private final CodeCacheProvider codeCache;
     private final ConstantReflectionProvider constantReflection;
+    private final StackIntrospection stackIntrospection;
 
-    public JVMCIBackend(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection) {
+    public JVMCIBackend(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, StackIntrospection stackIntrospection) {
         this.metaAccess = metaAccess;
         this.codeCache = codeCache;
         this.constantReflection = constantReflection;
+        this.stackIntrospection = stackIntrospection;
     }
 
     public MetaAccessProvider getMetaAccess() {
@@ -57,4 +62,8 @@
     public TargetDescription getTarget() {
         return codeCache.getTarget();
     }
+
+    public StackIntrospection getStackIntrospection() {
+        return stackIntrospection;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompiler.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime;
+
+import jdk.vm.ci.code.CompilationRequest;
+
+public interface JVMCICompiler {
+    int INVOCATION_ENTRY_BCI = -1;
+
+    /**
+     * Services a compilation request. This object should compile the method to machine code and
+     * install it in the code cache if the compilation is successful.
+     */
+    void compileMethod(CompilationRequest request);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCICompilerFactory.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.runtime;
+
+/**
+ * Factory for a JVMCI compiler.
+ */
+public interface JVMCICompilerFactory {
+
+    /**
+     * Get the name of this compiler. The compiler will be selected when the jvmci.compiler system
+     * property is equal to this name.
+     */
+    String getCompilerName();
+
+    /**
+     * Create a new instance of the {@link JVMCICompiler}.
+     */
+    JVMCICompiler createCompiler(JVMCIRuntime runtime);
+
+    /**
+     * In a tiered system it might be advantageous for startup to keep the JVMCI compiler from
+     * compiling itself so provide a hook to request that certain packages are compiled only by an
+     * optimizing first tier. The prefixes should class or package names using / as the separator,
+     * i.e. jdk/vm/ci for instance.
+     *
+     * @return 0 or more Strings identifying packages that should by compiled by the first tier
+     *         only.
+     */
+    default String[] getTrivialPrefixes() {
+        return null;
+    }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 package jdk.vm.ci.runtime;
 
-import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.Architecture;
 
 /**
  * Interface for accessing the {@link JVMCI} APIs supported by the runtime.
@@ -30,6 +30,11 @@
 public interface JVMCIRuntime {
 
     /**
+     * Gets the default system compiler.
+     */
+    JVMCICompiler getCompiler();
+
+    /**
      * Gets the host JVMCI backend.
      */
     JVMCIBackend getHostJVMCIBackend();
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/jdk/vm/ci/service/processor/ServiceProviderProcessor.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/jdk/vm/ci/service/processor/ServiceProviderProcessor.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,18 +22,25 @@
  */
 package jdk.vm.ci.service.processor;
 
-import java.io.*;
-import java.util.*;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Set;
 
-import javax.annotation.processing.*;
-import javax.lang.model.*;
-import javax.lang.model.element.*;
-import javax.lang.model.type.*;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.MirroredTypeException;
+import javax.lang.model.type.TypeMirror;
 import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
 
-import jdk.vm.ci.service.*;
-
-import javax.tools.*;
+import jdk.vm.ci.service.ServiceProvider;
 
 @SupportedAnnotationTypes("jdk.vm.ci.service.ServiceProvider")
 public class ServiceProviderProcessor extends AbstractProcessor {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/.checkstyle_checks.xml	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/.checkstyle_checks.xml	Wed Jul 05 21:00:20 2017 +0200
@@ -32,6 +32,10 @@
     <module name="NoWhitespaceAfter">
       <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
     </module>
+    <module name="AvoidStarImport">
+       <property name="allowClassImports" value="false"/>
+       <property name="allowStaticMemberImports" value="false"/>
+    </module>
     <module name="NoWhitespaceBefore">
       <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
     </module>
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/ServiceProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/ServiceProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.service;
 
-import java.lang.annotation.*;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * Annotates a service provider than can be loaded via {@linkplain Services#load(Class)} or
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/Services.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/Services.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,10 @@
  */
 package jdk.vm.ci.service;
 
-import java.util.*;
+import java.util.Formatter;
+import java.util.Iterator;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
 
 /**
  * A mechanism for accessing service providers via JVMCI.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,14 +22,18 @@
  */
 package jdk.vm.ci.sparc;
 
-import static java.nio.ByteOrder.*;
-import static jdk.vm.ci.code.MemoryBarriers.*;
+import static java.nio.ByteOrder.BIG_ENDIAN;
+import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD;
+import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
+import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
 
-import java.util.*;
+import java.util.Set;
 
-import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.Register.RegisterCategory;
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.PlatformKind;
 
 /**
  * Represents the SPARC architecture.
@@ -37,95 +41,50 @@
 public class SPARC extends Architecture {
 
     public static final RegisterCategory CPU = new RegisterCategory("CPU");
+    public static final RegisterCategory FPUs = new RegisterCategory("FPUs");
+    public static final RegisterCategory FPUd = new RegisterCategory("FPUd");
+    public static final RegisterCategory FPUq = new RegisterCategory("FPUq");
 
     // General purpose registers
-    public static final Register r0 = new Register(0, 0, "g0", CPU);
-    public static final Register r1 = new Register(1, 1, "g1", CPU);
-    public static final Register r2 = new Register(2, 2, "g2", CPU);
-    public static final Register r3 = new Register(3, 3, "g3", CPU);
-    public static final Register r4 = new Register(4, 4, "g4", CPU);
-    public static final Register r5 = new Register(5, 5, "g5", CPU);
-    public static final Register r6 = new Register(6, 6, "g6", CPU);
-    public static final Register r7 = new Register(7, 7, "g7", CPU);
-
-    public static final Register r8 = new Register(8, 8, "o0", CPU);
-    public static final Register r9 = new Register(9, 9, "o1", CPU);
-    public static final Register r10 = new Register(10, 10, "o2", CPU);
-    public static final Register r11 = new Register(11, 11, "o3", CPU);
-    public static final Register r12 = new Register(12, 12, "o4", CPU);
-    public static final Register r13 = new Register(13, 13, "o5", CPU);
-    public static final Register r14 = new Register(14, 14, "o6", CPU);
-    public static final Register r15 = new Register(15, 15, "o7", CPU);
+    public static final Register g0 = new Register(0, 0, "g0", CPU);
+    public static final Register g1 = new Register(1, 1, "g1", CPU);
+    public static final Register g2 = new Register(2, 2, "g2", CPU);
+    public static final Register g3 = new Register(3, 3, "g3", CPU);
+    public static final Register g4 = new Register(4, 4, "g4", CPU);
+    public static final Register g5 = new Register(5, 5, "g5", CPU);
+    public static final Register g6 = new Register(6, 6, "g6", CPU);
+    public static final Register g7 = new Register(7, 7, "g7", CPU);
 
-    public static final Register r16 = new Register(16, 16, "l0", CPU);
-    public static final Register r17 = new Register(17, 17, "l1", CPU);
-    public static final Register r18 = new Register(18, 18, "l2", CPU);
-    public static final Register r19 = new Register(19, 19, "l3", CPU);
-    public static final Register r20 = new Register(20, 20, "l4", CPU);
-    public static final Register r21 = new Register(21, 21, "l5", CPU);
-    public static final Register r22 = new Register(22, 22, "l6", CPU);
-    public static final Register r23 = new Register(23, 23, "l7", CPU);
-
-    public static final Register r24 = new Register(24, 24, "i0", CPU);
-    public static final Register r25 = new Register(25, 25, "i1", CPU);
-    public static final Register r26 = new Register(26, 26, "i2", CPU);
-    public static final Register r27 = new Register(27, 27, "i3", CPU);
-    public static final Register r28 = new Register(28, 28, "i4", CPU);
-    public static final Register r29 = new Register(29, 29, "i5", CPU);
-    public static final Register r30 = new Register(30, 30, "i6", CPU);
-    public static final Register r31 = new Register(31, 31, "i7", CPU);
+    public static final Register o0 = new Register(8, 8, "o0", CPU);
+    public static final Register o1 = new Register(9, 9, "o1", CPU);
+    public static final Register o2 = new Register(10, 10, "o2", CPU);
+    public static final Register o3 = new Register(11, 11, "o3", CPU);
+    public static final Register o4 = new Register(12, 12, "o4", CPU);
+    public static final Register o5 = new Register(13, 13, "o5", CPU);
+    public static final Register o6 = new Register(14, 14, "o6", CPU);
+    public static final Register o7 = new Register(15, 15, "o7", CPU);
 
-    public static final Register g0 = r0;
-    public static final Register g1 = r1;
-    public static final Register g2 = r2;
-    public static final Register g3 = r3;
-    public static final Register g4 = r4;
-    public static final Register g5 = r5;
-    public static final Register g6 = r6;
-    public static final Register g7 = r7;
-
-    public static final Register o0 = r8;
-    public static final Register o1 = r9;
-    public static final Register o2 = r10;
-    public static final Register o3 = r11;
-    public static final Register o4 = r12;
-    public static final Register o5 = r13;
-    public static final Register o6 = r14;
-    public static final Register o7 = r15;
+    public static final Register l0 = new Register(16, 16, "l0", CPU);
+    public static final Register l1 = new Register(17, 17, "l1", CPU);
+    public static final Register l2 = new Register(18, 18, "l2", CPU);
+    public static final Register l3 = new Register(19, 19, "l3", CPU);
+    public static final Register l4 = new Register(20, 20, "l4", CPU);
+    public static final Register l5 = new Register(21, 21, "l5", CPU);
+    public static final Register l6 = new Register(22, 22, "l6", CPU);
+    public static final Register l7 = new Register(23, 23, "l7", CPU);
 
-    public static final Register l0 = r16;
-    public static final Register l1 = r17;
-    public static final Register l2 = r18;
-    public static final Register l3 = r19;
-    public static final Register l4 = r20;
-    public static final Register l5 = r21;
-    public static final Register l6 = r22;
-    public static final Register l7 = r23;
-
-    public static final Register i0 = r24;
-    public static final Register i1 = r25;
-    public static final Register i2 = r26;
-    public static final Register i3 = r27;
-    public static final Register i4 = r28;
-    public static final Register i5 = r29;
-    public static final Register i6 = r30;
-    public static final Register i7 = r31;
+    public static final Register i0 = new Register(24, 24, "i0", CPU);
+    public static final Register i1 = new Register(25, 25, "i1", CPU);
+    public static final Register i2 = new Register(26, 26, "i2", CPU);
+    public static final Register i3 = new Register(27, 27, "i3", CPU);
+    public static final Register i4 = new Register(28, 28, "i4", CPU);
+    public static final Register i5 = new Register(29, 29, "i5", CPU);
+    public static final Register i6 = new Register(30, 30, "i6", CPU);
+    public static final Register i7 = new Register(31, 31, "i7", CPU);
 
     public static final Register sp = o6;
     public static final Register fp = i6;
 
-    // @formatter:off
-    public static final Register[] cpuRegisters = {
-        r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
-        r8,  r9,  r10, r11, r12, r13, r14, r15,
-        r16, r17, r18, r19, r20, r21, r22, r23,
-        r24, r25, r26, r27, r28, r29, r30, r31
-    };
-    // @formatter:on
-
-    public static final RegisterCategory FPUs = new RegisterCategory("FPUs", cpuRegisters.length);
-    public static final RegisterCategory FPUd = new RegisterCategory("FPUd", cpuRegisters.length + 32);
-
     // Floating point registers
     public static final Register f0 = new Register(32, 0, "f0", FPUs);
     public static final Register f1 = new Register(33, 1, "f1", FPUs);
@@ -163,67 +122,111 @@
     public static final Register f30 = new Register(62, 30, "f30", FPUs);
     public static final Register f31 = new Register(63, 31, "f31", FPUs);
 
-    public static final Register d0 = new Register(32, getDoubleEncoding(0), "d0", FPUs);
-    public static final Register d2 = new Register(34, getDoubleEncoding(2), "d2", FPUs);
-    public static final Register d4 = new Register(36, getDoubleEncoding(4), "d4", FPUs);
-    public static final Register d6 = new Register(38, getDoubleEncoding(6), "d6", FPUs);
-    public static final Register d8 = new Register(40, getDoubleEncoding(8), "d8", FPUs);
-    public static final Register d10 = new Register(42, getDoubleEncoding(10), "d10", FPUs);
-    public static final Register d12 = new Register(44, getDoubleEncoding(12), "d12", FPUs);
-    public static final Register d14 = new Register(46, getDoubleEncoding(14), "d14", FPUs);
+    // Double precision registers
+    public static final Register d0 = new Register(64, getDoubleEncoding(0), "d0", FPUd);
+    public static final Register d2 = new Register(65, getDoubleEncoding(2), "d2", FPUd);
+    public static final Register d4 = new Register(66, getDoubleEncoding(4), "d4", FPUd);
+    public static final Register d6 = new Register(67, getDoubleEncoding(6), "d6", FPUd);
+    public static final Register d8 = new Register(68, getDoubleEncoding(8), "d8", FPUd);
+    public static final Register d10 = new Register(69, getDoubleEncoding(10), "d10", FPUd);
+    public static final Register d12 = new Register(70, getDoubleEncoding(12), "d12", FPUd);
+    public static final Register d14 = new Register(71, getDoubleEncoding(14), "d14", FPUd);
 
-    public static final Register d16 = new Register(48, getDoubleEncoding(16), "d16", FPUs);
-    public static final Register d18 = new Register(50, getDoubleEncoding(18), "d18", FPUs);
-    public static final Register d20 = new Register(52, getDoubleEncoding(20), "d20", FPUs);
-    public static final Register d22 = new Register(54, getDoubleEncoding(22), "d22", FPUs);
-    public static final Register d24 = new Register(56, getDoubleEncoding(24), "d24", FPUs);
-    public static final Register d26 = new Register(58, getDoubleEncoding(26), "d26", FPUs);
-    public static final Register d28 = new Register(60, getDoubleEncoding(28), "d28", FPUs);
-    public static final Register d30 = new Register(62, getDoubleEncoding(28), "d28", FPUs);
+    public static final Register d16 = new Register(72, getDoubleEncoding(16), "d16", FPUd);
+    public static final Register d18 = new Register(73, getDoubleEncoding(18), "d18", FPUd);
+    public static final Register d20 = new Register(74, getDoubleEncoding(20), "d20", FPUd);
+    public static final Register d22 = new Register(75, getDoubleEncoding(22), "d22", FPUd);
+    public static final Register d24 = new Register(76, getDoubleEncoding(24), "d24", FPUd);
+    public static final Register d26 = new Register(77, getDoubleEncoding(26), "d26", FPUd);
+    public static final Register d28 = new Register(78, getDoubleEncoding(28), "d28", FPUd);
+    public static final Register d30 = new Register(79, getDoubleEncoding(28), "d28", FPUd);
+
+    public static final Register d32 = new Register(80, getDoubleEncoding(32), "d32", FPUd);
+    public static final Register d34 = new Register(81, getDoubleEncoding(34), "d34", FPUd);
+    public static final Register d36 = new Register(82, getDoubleEncoding(36), "d36", FPUd);
+    public static final Register d38 = new Register(83, getDoubleEncoding(38), "d38", FPUd);
+    public static final Register d40 = new Register(84, getDoubleEncoding(40), "d40", FPUd);
+    public static final Register d42 = new Register(85, getDoubleEncoding(42), "d42", FPUd);
+    public static final Register d44 = new Register(86, getDoubleEncoding(44), "d44", FPUd);
+    public static final Register d46 = new Register(87, getDoubleEncoding(46), "d46", FPUd);
 
-    public static final Register d32 = new Register(64, getDoubleEncoding(32), "d32", FPUd);
-    public static final Register d34 = new Register(65, getDoubleEncoding(34), "d34", FPUd);
-    public static final Register d36 = new Register(66, getDoubleEncoding(36), "d36", FPUd);
-    public static final Register d38 = new Register(67, getDoubleEncoding(38), "d38", FPUd);
-    public static final Register d40 = new Register(68, getDoubleEncoding(40), "d40", FPUd);
-    public static final Register d42 = new Register(69, getDoubleEncoding(42), "d42", FPUd);
-    public static final Register d44 = new Register(70, getDoubleEncoding(44), "d44", FPUd);
-    public static final Register d46 = new Register(71, getDoubleEncoding(46), "d46", FPUd);
+    public static final Register d48 = new Register(88, getDoubleEncoding(48), "d48", FPUd);
+    public static final Register d50 = new Register(89, getDoubleEncoding(50), "d50", FPUd);
+    public static final Register d52 = new Register(90, getDoubleEncoding(52), "d52", FPUd);
+    public static final Register d54 = new Register(91, getDoubleEncoding(54), "d54", FPUd);
+    public static final Register d56 = new Register(92, getDoubleEncoding(56), "d56", FPUd);
+    public static final Register d58 = new Register(93, getDoubleEncoding(58), "d58", FPUd);
+    public static final Register d60 = new Register(94, getDoubleEncoding(60), "d60", FPUd);
+    public static final Register d62 = new Register(95, getDoubleEncoding(62), "d62", FPUd);
 
-    public static final Register d48 = new Register(72, getDoubleEncoding(48), "d48", FPUd);
-    public static final Register d50 = new Register(73, getDoubleEncoding(50), "d50", FPUd);
-    public static final Register d52 = new Register(74, getDoubleEncoding(52), "d52", FPUd);
-    public static final Register d54 = new Register(75, getDoubleEncoding(54), "d54", FPUd);
-    public static final Register d56 = new Register(76, getDoubleEncoding(56), "d56", FPUd);
-    public static final Register d58 = new Register(77, getDoubleEncoding(58), "d58", FPUd);
-    public static final Register d60 = new Register(78, getDoubleEncoding(60), "d60", FPUd);
-    public static final Register d62 = new Register(79, getDoubleEncoding(62), "d62", FPUd);
+    // Quad precision registers
+    public static final Register q0 = new Register(96, getQuadncoding(0), "q0", FPUq);
+    public static final Register q4 = new Register(97, getQuadncoding(4), "q4", FPUq);
+    public static final Register q8 = new Register(98, getQuadncoding(8), "q8", FPUq);
+    public static final Register q12 = new Register(99, getQuadncoding(12), "q12", FPUq);
+    public static final Register q16 = new Register(100, getQuadncoding(16), "q16", FPUq);
+    public static final Register q20 = new Register(101, getQuadncoding(20), "q20", FPUq);
+    public static final Register q24 = new Register(102, getQuadncoding(24), "q24", FPUq);
+    public static final Register q28 = new Register(103, getQuadncoding(28), "q28", FPUq);
+
+    public static final Register q32 = new Register(104, getQuadncoding(32), "q32", FPUq);
+    public static final Register q36 = new Register(105, getQuadncoding(36), "q36", FPUq);
+    public static final Register q40 = new Register(106, getQuadncoding(40), "q40", FPUq);
+    public static final Register q44 = new Register(107, getQuadncoding(44), "q44", FPUq);
+    public static final Register q48 = new Register(108, getQuadncoding(48), "q48", FPUq);
+    public static final Register q52 = new Register(109, getQuadncoding(52), "q52", FPUq);
+    public static final Register q56 = new Register(110, getQuadncoding(56), "q56", FPUq);
+    public static final Register q60 = new Register(111, getQuadncoding(60), "q60", FPUq);
 
     // @formatter:off
-    public static final Register[] fpuRegisters = {
+    public static final Register[] cpuRegisters = {
+        g0,  g1,  g2,  g3,  g4,  g5,  g6,  g7,
+        o0,  o1,  o2,  o3,  o4,  o5,  o6,  o7,
+        l0,  l1,  l2,  l3,  l4,  l5,  l6,  l7,
+        i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7
+    };
+
+    public static final Register[] fpusRegisters = {
+        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+        f8,  f9,  f10, f11, f12, f13, f14, f15,
+        f16, f17, f18, f19, f20, f21, f22, f23,
+        f24, f25, f26, f27, f28, f29, f30, f31
+    };
+
+    public static final Register[] fpudRegisters = {
+        d0, d2, d4, d6, d8,  d10, d12, d14,
+        d16, d18, d20, d22, d24, d26, d28, d30,
+        d32, d34, d36, d38, d40, d42, d44, d46,
+        d48, d50, d52, d54, d56, d58, d60, d62
+    };
+
+    public static final Register[] fpuqRegisters = {
+        q0, q4, q8, q12,
+        q16, q20, q24, q28,
+        q32, q36, q40, q44,
+        q48, q52, q56, q60,
+    };
+
+    public static final Register[] allRegisters = {
+        g0,  g1,  g2,  g3,  g4,  g5,  g6,  g7,
+        o0,  o1,  o2,  o3,  o4,  o5,  o6,  o7,
+        l0,  l1,  l2,  l3,  l4,  l5,  l6,  l7,
+        i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7,
+
         f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
         f8,  f9,  f10, f11, f12, f13, f14, f15,
         f16, f17, f18, f19, f20, f21, f22, f23,
         f24, f25, f26, f27, f28, f29, f30, f31,
-        d32, d34, d36, d38, d40, d42, d44, d46,
-        d48, d50, d52, d54, d56, d58, d60, d62
-    };
-    // @formatter:on
 
-    // @formatter:off
-    public static final Register[] allRegisters = {
-        // CPU
-        r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
-        r8,  r9,  r10, r11, r12, r13, r14, r15,
-        r16, r17, r18, r19, r20, r21, r22, r23,
-        r24, r25, r26, r27, r28, r29, r30, r31,
-        // FPU
-        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
-        f8,  f9,  f10, f11, f12, f13, f14, f15,
-        f16, f17, f18, f19, f20, f21, f22, f23,
-        f24, f25, f26, f27, f28, f29, f30, f31,
+        d0, d2, d4, d6, d8,  d10, d12, d14,
+        d16, d18, d20, d22, d24, d26, d28, d30,
         d32, d34, d36, d38, d40, d42, d44, d46,
-        d48, d50, d52, d54, d56, d58, d60, d62
+        d48, d50, d52, d54, d56, d58, d60, d62,
+
+        q0, q4, q8, q12,
+        q16, q20, q24, q28,
+        q32, q36, q40, q44,
+        q48, q52, q56, q60,
     };
     // @formatter:on
 
@@ -231,18 +234,6 @@
      * Stack bias for stack and frame pointer loads.
      */
     public static final int STACK_BIAS = 0x7ff;
-    /**
-     * In fact there are 64 single floating point registers, 32 of them could be accessed. TODO:
-     * Improve handling of these float registers
-     */
-    public static final int FLOAT_REGISTER_COUNT = 64;
-
-    /**
-     * Alignment for valid memory access.
-     */
-    public static final int MEMORY_ACCESS_ALIGN = 4;
-
-    public static final int INSTRUCTION_SIZE = 4;
 
     /**
      * Size to keep free for flushing the register-window to stack.
@@ -252,90 +243,87 @@
     public final Set<CPUFeature> features;
 
     public SPARC(Set<CPUFeature> features) {
-        super("SPARC", JavaKind.Long, BIG_ENDIAN, false, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, r31.encoding + FLOAT_REGISTER_COUNT + 1, 8);
+        super("SPARC", SPARCKind.XWORD, BIG_ENDIAN, false, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8);
         this.features = features;
     }
 
     @Override
-    public boolean canStoreValue(RegisterCategory category, PlatformKind lirKind) {
-        if (!(lirKind instanceof JavaKind)) {
-            return false;
-        }
+    public Register[] getAvailableValueRegisters() {
+        return allRegisters;
+    }
 
-        JavaKind kind = (JavaKind) lirKind;
-        if (category.equals(CPU)) {
-            switch (kind) {
-                case Boolean:
-                case Byte:
-                case Char:
-                case Short:
-                case Int:
-                case Long:
-                    return true;
-            }
-        } else if (category.equals(FPUs) && kind.equals(JavaKind.Float)) {
-            return true;
-        } else if (category.equals(FPUd) && kind.equals(JavaKind.Double)) {
-            return true;
+    @Override
+    public boolean canStoreValue(RegisterCategory category, PlatformKind kind) {
+        SPARCKind sparcKind = (SPARCKind) kind;
+        switch (sparcKind) {
+            case BYTE:
+            case HWORD:
+            case WORD:
+            case XWORD:
+                return CPU.equals(category);
+            case SINGLE:
+            case V32_BYTE:
+            case V32_HWORD:
+                return FPUs.equals(category);
+            case DOUBLE:
+            case V64_BYTE:
+            case V64_HWORD:
+            case V64_WORD:
+            case V64_SINGLE:
+                return FPUd.equals(category);
+            case QUAD:
+                return FPUq.equals(category);
+            default:
+                return false;
         }
-        return false;
     }
 
     @Override
     public PlatformKind getLargestStorableKind(RegisterCategory category) {
         if (category.equals(CPU)) {
-            return JavaKind.Long;
+            return SPARCKind.XWORD;
         } else if (category.equals(FPUd)) {
-            return JavaKind.Double;
+            return SPARCKind.DOUBLE;
         } else if (category.equals(FPUs)) {
-            return JavaKind.Float;
+            return SPARCKind.SINGLE;
+        } else if (category.equals(FPUq)) {
+            return SPARCKind.QUAD;
         } else {
-            return JavaKind.Illegal;
+            throw new IllegalArgumentException("Unknown register category: " + category);
         }
     }
 
     @Override
     public PlatformKind getPlatformKind(JavaKind javaKind) {
-        if (javaKind.isObject()) {
-            return JavaKind.Long;
-        } else {
-            return javaKind;
+        switch (javaKind) {
+            case Boolean:
+            case Byte:
+                return SPARCKind.BYTE;
+            case Short:
+            case Char:
+                return SPARCKind.HWORD;
+            case Int:
+                return SPARCKind.WORD;
+            case Long:
+            case Object:
+                return SPARCKind.XWORD;
+            case Float:
+                return SPARCKind.SINGLE;
+            case Double:
+                return SPARCKind.DOUBLE;
+            default:
+                throw new IllegalArgumentException("Unknown JavaKind: " + javaKind);
         }
     }
 
-    public static int spillSlotSize(TargetDescription td, PlatformKind kind) {
-        return Math.max(td.getSizeInBytes(kind), MEMORY_ACCESS_ALIGN);
-    }
-
-    public static int getDoubleEncoding(int reg) {
+    private static int getDoubleEncoding(int reg) {
         assert reg < 64 && ((reg & 1) == 0);
-        // ignore v8 assertion for now
         return (reg & 0x1e) | ((reg & 0x20) >> 5);
     }
 
-    public static boolean isCPURegister(Register r) {
-        return r.getRegisterCategory().equals(CPU);
-    }
-
-    public static boolean isCPURegister(Register... regs) {
-        for (Register reg : regs) {
-            if (!isCPURegister(reg)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public static boolean isGlobalRegister(Register r) {
-        return isCPURegister(r) && g0.number <= r.number && r.number <= g7.number;
-    }
-
-    public static boolean isSingleFloatRegister(Register r) {
-        return r.name.startsWith("f");
-    }
-
-    public static boolean isDoubleFloatRegister(Register r) {
-        return r.name.startsWith("d");
+    private static int getQuadncoding(int reg) {
+        assert reg < 64 && ((reg & 1) == 0);
+        return (reg & 0x1c) | ((reg & 0x20) >> 5);
     }
 
     public Set<CPUFeature> getFeatures() {
@@ -351,6 +339,24 @@
         VIS2,
         VIS3,
         CBCOND,
-        BLOCK_ZEROING
+        V8,
+        HARDWARE_MUL32,
+        HARDWARE_DIV32,
+        HARDWARE_FSMULD,
+        HARDWARE_POPC,
+        V9,
+        SUN4V,
+        BLK_INIT_INSTRUCTIONS,
+        FMAF,
+        FMAU,
+        SPARC64_FAMILY,
+        M_FAMILY,
+        T_FAMILY,
+        T1_MODEL,
+        SPARC5,
+        AES,
+        SHA1,
+        SHA256,
+        SHA512
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARCKind.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.sparc;
+
+import jdk.vm.ci.meta.PlatformKind;
+
+public enum SPARCKind implements PlatformKind {
+    BYTE(1),
+    HWORD(2),
+    WORD(4),
+    XWORD(8),
+    SINGLE(4),
+    DOUBLE(8),
+    QUAD(16),
+
+    V32_BYTE(4, BYTE),
+    V32_HWORD(4, HWORD),
+
+    V64_BYTE(8, BYTE),
+    V64_HWORD(8, HWORD),
+    V64_WORD(8, WORD),
+    V64_SINGLE(8, SINGLE);
+
+    private final int size;
+    private final int vectorLength;
+
+    private final SPARCKind scalar;
+    private final EnumKey<SPARCKind> key = new EnumKey<>(this);
+
+    private SPARCKind(int size) {
+        this.size = size;
+        this.scalar = this;
+        this.vectorLength = 1;
+    }
+
+    private SPARCKind(int size, SPARCKind scalar) {
+        this.size = size;
+        this.scalar = scalar;
+
+        assert size % scalar.size == 0;
+        this.vectorLength = size / scalar.size;
+    }
+
+    public SPARCKind getScalar() {
+        return scalar;
+    }
+
+    public int getSizeInBytes() {
+        return size;
+    }
+
+    public int getSizeInBits() {
+        return getSizeInBytes() * 8;
+    }
+
+    public int getVectorLength() {
+        return vectorLength;
+    }
+
+    public Key getKey() {
+        return key;
+    }
+
+    public boolean isInteger() {
+        switch (this) {
+            case BYTE:
+            case HWORD:
+            case WORD:
+            case XWORD:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public boolean isFloat() {
+        return !isInteger();
+    }
+
+    public char getTypeChar() {
+        switch (this) {
+            case BYTE:
+                return 'b';
+            case HWORD:
+                return 'h';
+            case WORD:
+                return 'w';
+            case XWORD:
+                return 'd';
+            case SINGLE:
+                return 'S';
+            case DOUBLE:
+            case V64_BYTE:
+            case V64_HWORD:
+            case V64_WORD:
+                return 'D';
+            default:
+                return '-';
+        }
+    }
+}
--- a/hotspot/src/os/aix/vm/os_aix.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -3811,7 +3811,7 @@
 // able to use structured exception handling (thread-local exception filters)
 // on, e.g., Win32.
 void
-os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method,
+os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method,
                          JavaCallArguments* args, Thread* thread) {
   f(value, method, args, thread);
 }
--- a/hotspot/src/os/bsd/dtrace/libjvm_db.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os/bsd/dtrace/libjvm_db.c	Wed Jul 05 21:00:20 2017 +0200
@@ -834,7 +834,7 @@
       if (stream_bci == vf->bci) {
           /* perfect match */
           if (debug > 2)
-              fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line);
+              fprintf(stderr, "\t line_number_from_bci: END: exact line: %d \n\n", vf->line);
           vf->line = stream_line;
           return PS_OK;
       } else {
@@ -843,14 +843,14 @@
               best_bci = stream_bci;
               vf->line = stream_line;
               if (debug > 2) {
-                  fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n",
+                  fprintf(stderr, "\t line_number_from_bci: best_bci: %d, best_line: %d\n",
                                    best_bci, vf->line);
               }
           }
       }
   }
   if (debug > 2)
-      fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line);
+      fprintf(stderr, "\t line_number_from_bci: END: line: %d \n\n", vf->line);
   return PS_OK;
 
  fail:
@@ -1002,7 +1002,7 @@
       err = line_number_from_bci(N->J, vf);
       CHECK_FAIL(err);
       if (debug > 2) {
-        fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n",
+        fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %d\n",
                 vf->method, vf->line);
       }
     }
@@ -1338,7 +1338,7 @@
   jframe->bci = vf->bci;
   jframe->line = vf->line;
   if (debug) {
-      fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
+      fprintf(stderr, "\t Jget_vframe: method name: %s, line: %d\n",
                        name, vf->line);
   }
   return PS_OK;
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -440,6 +440,10 @@
     if (pslash != NULL) {
       *pslash = '\0';            // Get rid of /{client|server|hotspot}.
     }
+#ifdef STATIC_BUILD
+    strcat(buf, "/lib");
+#endif
+
     Arguments::set_dll_dir(buf);
 
     if (pslash != NULL) {
@@ -1388,6 +1392,9 @@
 
 #ifdef __APPLE__
 void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
+#ifdef STATIC_BUILD
+  return os::get_default_process_handle();
+#else
   void * result= ::dlopen(filename, RTLD_LAZY);
   if (result != NULL) {
     // Successful loading
@@ -1399,9 +1406,13 @@
   ebuf[ebuflen-1]='\0';
 
   return NULL;
+#endif // STATIC_BUILD
 }
 #else
 void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
+#ifdef STATIC_BUILD
+  return os::get_default_process_handle();
+#else
   void * result= ::dlopen(filename, RTLD_LAZY);
   if (result != NULL) {
     // Successful loading
@@ -1574,6 +1585,7 @@
   }
 
   return NULL;
+#endif // STATIC_BUILD
 }
 #endif // !__APPLE__
 
@@ -3745,7 +3757,7 @@
 // able to use structured exception handling (thread-local exception filters)
 // on, e.g., Win32.
 void os::os_exception_wrapper(java_call_t f, JavaValue* value,
-                              methodHandle* method, JavaCallArguments* args,
+                              const methodHandle& method, JavaCallArguments* args,
                               Thread* thread) {
   f(value, method, args, thread);
 }
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -2794,7 +2794,7 @@
 
 
 int os::Linux::sched_getcpu_syscall(void) {
-  unsigned int cpu;
+  unsigned int cpu = 0;
   int retval = -1;
 
 #if defined(IA32)
@@ -4187,8 +4187,8 @@
       sigaddset(&(actp->sa_mask), sig);
     }
 
-    sa_handler_t hand;
-    sa_sigaction_t sa;
+    sa_handler_t hand = NULL;
+    sa_sigaction_t sa = NULL;
     bool siginfo_flag_set = (actp->sa_flags & SA_SIGINFO) != 0;
     // retrieve the chained handler
     if (siginfo_flag_set) {
@@ -4393,7 +4393,7 @@
 
 static const char* get_signal_handler_name(address handler,
                                            char* buf, int buflen) {
-  int offset;
+  int offset = 0;
   bool found = os::dll_address_to_library_name(handler, buf, buflen, &offset);
   if (found) {
     // skip directory names
@@ -4960,7 +4960,7 @@
 // able to use structured exception handling (thread-local exception filters)
 // on, e.g., Win32.
 void
-os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method,
+os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method,
                          JavaCallArguments* args, Thread* thread) {
   f(value, method, args, thread);
 }
--- a/hotspot/src/os/solaris/dtrace/libjvm_db.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c	Wed Jul 05 21:00:20 2017 +0200
@@ -834,7 +834,7 @@
       if (stream_bci == vf->bci) {
           /* perfect match */
           if (debug > 2)
-              fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line);
+              fprintf(stderr, "\t line_number_from_bci: END: exact line: %d \n\n", vf->line);
           vf->line = stream_line;
           return PS_OK;
       } else {
@@ -843,14 +843,14 @@
               best_bci = stream_bci;
               vf->line = stream_line;
               if (debug > 2) {
-                  fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n",
+                  fprintf(stderr, "\t line_number_from_bci: best_bci: %d, best_line: %d\n",
                                    best_bci, vf->line);
               }
           }
       }
   }
   if (debug > 2)
-      fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line);
+      fprintf(stderr, "\t line_number_from_bci: END: line: %d \n\n", vf->line);
   return PS_OK;
 
  fail:
@@ -1002,7 +1002,7 @@
       err = line_number_from_bci(N->J, vf);
       CHECK_FAIL(err);
       if (debug > 2) {
-        fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n",
+        fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %d\n",
                 vf->method, vf->line);
       }
     }
@@ -1338,7 +1338,7 @@
   jframe->bci = vf->bci;
   jframe->line = vf->line;
   if (debug) {
-      fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
+      fprintf(stderr, "\t Jget_vframe: method name: %s, line: %d\n",
                        name, vf->line);
   }
   return PS_OK;
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -3774,7 +3774,7 @@
 // This does not do anything on Solaris. This is basically a hook for being
 // able to use structured exception handling (thread-local exception filters) on, e.g., Win32.
 void os::os_exception_wrapper(java_call_t f, JavaValue* value,
-                              methodHandle* method, JavaCallArguments* args,
+                              const methodHandle& method, JavaCallArguments* args,
                               Thread* thread) {
   f(value, method, args, thread);
 }
--- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -65,6 +65,8 @@
 }
 inline void os::dll_unload(void *lib) { ::dlclose(lib); }
 
+inline const int os::default_file_open_flags() { return 0;}
+
 inline DIR* os::opendir(const char* dirname) {
   assert(dirname != NULL, "just checking");
   return ::opendir(dirname);
--- a/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os_cpu/linux_x86/vm/copy_linux_x86.inline.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -30,7 +30,7 @@
   (void)memmove(to, from, count * HeapWordSize);
 #else
   // Includes a zero-count check.
-  intx temp;
+  intx temp = 0;
   __asm__ volatile("        testl   %6,%6         ;"
                    "        jz      7f            ;"
                    "        cmpl    %4,%5         ;"
@@ -88,7 +88,7 @@
   }
 #else
   // Includes a zero-count check.
-  intx temp;
+  intx temp = 0;
   __asm__ volatile("        testl   %6,%6       ;"
                    "        jz      3f          ;"
                    "        cmpl    $32,%6      ;"
@@ -145,7 +145,7 @@
   (void)memmove(to, from, count);
 #else
   // Includes a zero-count check.
-  intx temp;
+  intx temp = 0;
   __asm__ volatile("        testl   %6,%6          ;"
                    "        jz      13f            ;"
                    "        cmpl    %4,%5          ;"
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,7 +71,7 @@
 extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* );
 
 // Install a win32 structured exception handler around thread.
-void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) {
+void os::os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method, JavaCallArguments* args, Thread* thread) {
   __try {
 
 #ifndef AMD64
--- a/hotspot/src/share/vm/adlc/formssel.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -607,6 +607,8 @@
       ( strcmp(_matrule->_rChild->_opType,"StrComp"    )==0 ||
         strcmp(_matrule->_rChild->_opType,"StrEquals"  )==0 ||
         strcmp(_matrule->_rChild->_opType,"StrIndexOf" )==0 ||
+        strcmp(_matrule->_rChild->_opType,"StrIndexOfChar" )==0 ||
+        strcmp(_matrule->_rChild->_opType,"HasNegatives" )==0 ||
         strcmp(_matrule->_rChild->_opType,"AryEq"      )==0 ))
     return true;
 
@@ -887,11 +889,16 @@
       ( strcmp(_matrule->_rChild->_opType,"AryEq"     )==0 ||
         strcmp(_matrule->_rChild->_opType,"StrComp"   )==0 ||
         strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 ||
+        strcmp(_matrule->_rChild->_opType,"StrInflatedCopy"   )==0 ||
+        strcmp(_matrule->_rChild->_opType,"StrCompressedCopy" )==0 ||
         strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 ||
+        strcmp(_matrule->_rChild->_opType,"StrIndexOfChar")==0 ||
+        strcmp(_matrule->_rChild->_opType,"HasNegatives")==0 ||
         strcmp(_matrule->_rChild->_opType,"EncodeISOArray")==0)) {
         // String.(compareTo/equals/indexOf) and Arrays.equals
         // and sun.nio.cs.iso8859_1$Encoder.EncodeISOArray
         // take 1 control and 1 memory edges.
+        // Also String.(compressedCopy/inflatedCopy).
     return 2;
   }
 
--- a/hotspot/src/share/vm/adlc/main.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/adlc/main.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -221,6 +221,7 @@
   AD.addInclude(AD._CPP_file, "oops/method.hpp");
   AD.addInclude(AD._CPP_file, "oops/oop.inline.hpp");
   AD.addInclude(AD._CPP_file, "opto/cfgnode.hpp");
+  AD.addInclude(AD._CPP_file, "opto/intrinsicnode.hpp");
   AD.addInclude(AD._CPP_file, "opto/locknode.hpp");
   AD.addInclude(AD._CPP_file, "opto/opcodes.hpp");
   AD.addInclude(AD._CPP_file, "opto/regalloc.hpp");
@@ -256,6 +257,7 @@
   AD.addInclude(AD._DFA_file, "precompiled.hpp");
   AD.addInclude(AD._DFA_file, "adfiles", get_basename(AD._HPP_file._name));
   AD.addInclude(AD._DFA_file, "opto/cfgnode.hpp");  // Use PROB_MAX in predicate.
+  AD.addInclude(AD._DFA_file, "opto/intrinsicnode.hpp");
   AD.addInclude(AD._DFA_file, "opto/matcher.hpp");
   AD.addInclude(AD._DFA_file, "opto/opcodes.hpp");
   AD.addInclude(AD._DFA_file, "opto/convertnode.hpp");
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -509,7 +509,7 @@
   }
 }
 
-void CodeBuffer::finalize_oop_references(methodHandle mh) {
+void CodeBuffer::finalize_oop_references(const methodHandle& mh) {
   No_Safepoint_Verifier nsv;
 
   GrowableArray<oop> oops;
--- a/hotspot/src/share/vm/asm/codeBuffer.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/asm/codeBuffer.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -541,7 +541,7 @@
   bool insts_contains2(address pc) const { return _insts.contains2(pc); }
 
   // Record any extra oops required to keep embedded metadata alive
-  void finalize_oop_references(methodHandle method);
+  void finalize_oop_references(const methodHandle& method);
 
   // Allocated size in all sections, when aligned and concatenated
   // (this is the eventual state of the content in its final
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -639,7 +639,7 @@
 
   if (l == r && !lt->is_float_kind()) {
     // pattern: If (a cond a) => simplify to Goto
-    BlockBegin* sux;
+    BlockBegin* sux = NULL;
     switch (x->cond()) {
     case If::eql: sux = x->sux_for(true);  break;
     case If::neq: sux = x->sux_for(false); break;
@@ -647,6 +647,7 @@
     case If::leq: sux = x->sux_for(true);  break;
     case If::gtr: sux = x->sux_for(false); break;
     case If::geq: sux = x->sux_for(true);  break;
+    default: ShouldNotReachHere();
     }
     // If is a safepoint then the debug information should come from the state_before of the If.
     set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
@@ -684,7 +685,7 @@
       } else {
         // two successors differ and two successors are the same => simplify to: If (x cmp y)
         // determine new condition & successors
-        If::Condition cond;
+        If::Condition cond = If::eql;
         BlockBegin* tsux = NULL;
         BlockBegin* fsux = NULL;
              if (lss_sux == eql_sux) { cond = If::leq; tsux = lss_sux; fsux = gtr_sux; }
@@ -727,7 +728,9 @@
         set_canonical(new IfInstanceOf(inst->klass(), inst->obj(), true, inst->state_before()->bci(), is_inst_sux, no_inst_sux));
       }
     }
-  } else if (rt == objectNull && (l->as_NewInstance() || l->as_NewArray())) {
+  } else if (rt == objectNull &&
+           (l->as_NewInstance() || l->as_NewArray() ||
+             (UseNewCode && l->as_Local() && l->as_Local()->is_receiver()))) {
     if (x->cond() == Instruction::eql) {
       BlockBegin* sux = x->fsux();
       set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux)));
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,7 @@
   return buffer_blob;
 }
 
-bool Compiler::is_intrinsic_supported(methodHandle method) {
+bool Compiler::is_intrinsic_supported(const methodHandle& method) {
   vmIntrinsics::ID id = method->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
 
@@ -225,6 +225,8 @@
   case vmIntrinsics::_updateByteBufferCRC32:
   case vmIntrinsics::_compareAndSwapInt:
   case vmIntrinsics::_compareAndSwapObject:
+  case vmIntrinsics::_getCharStringU:
+  case vmIntrinsics::_putCharStringU:
 #ifdef TRACE_HAVE_INTRINSICS
   case vmIntrinsics::_classID:
   case vmIntrinsics::_threadID:
--- a/hotspot/src/share/vm/c1/c1_Compiler.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,7 @@
   virtual void print_timers();
 
   // Check if the C1 compiler supports an intrinsic for 'method'.
-  virtual bool is_intrinsic_supported(methodHandle method);
+  virtual bool is_intrinsic_supported(const methodHandle& method);
 
   // Size of the code buffer
   static int code_buffer_size();
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -3089,7 +3089,7 @@
   int idx = 0;
   if (!method()->is_static()) {
     // we should always see the receiver
-    state->store_local(idx, new Local(method()->holder(), objectType, idx));
+    state->store_local(idx, new Local(method()->holder(), objectType, idx, true));
     idx = 1;
   }
 
@@ -3101,7 +3101,7 @@
     // don't allow T_ARRAY to propagate into locals types
     if (basic_type == T_ARRAY) basic_type = T_OBJECT;
     ValueType* vt = as_ValueType(basic_type);
-    state->store_local(idx, new Local(type, vt, idx));
+    state->store_local(idx, new Local(type, vt, idx, false));
     idx += type->size();
   }
 
@@ -3445,6 +3445,8 @@
   case vmIntrinsics::_getAndSetInt       :
   case vmIntrinsics::_getAndSetLong      :
   case vmIntrinsics::_getAndSetObject    : append_unsafe_get_and_set_obj(callee, false); return;
+  case vmIntrinsics::_getCharStringU     : append_char_access(callee, false); return;
+  case vmIntrinsics::_putCharStringU     : append_char_access(callee, true); return;
   default:
     break;
   }
@@ -3823,8 +3825,8 @@
   caller_state->truncate_stack(args_base);
   assert(callee_state->stack_size() == 0, "callee stack must be empty");
 
-  Value lock;
-  BlockBegin* sync_handler;
+  Value lock = NULL;
+  BlockBegin* sync_handler = NULL;
 
   // Inline the locking of the receiver if the callee is synchronized
   if (callee->is_synchronized()) {
@@ -4179,6 +4181,30 @@
   compilation()->set_has_unsafe_access(true);
 }
 
+void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) {
+  // This intrinsic accesses byte[] array as char[] array. Computing the offsets
+  // correctly requires matched array shapes.
+  assert (arrayOopDesc::base_offset_in_bytes(T_CHAR) == arrayOopDesc::base_offset_in_bytes(T_BYTE),
+          "sanity: byte[] and char[] bases agree");
+  assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2,
+          "sanity: byte[] and char[] scales agree");
+
+  ValueStack* state_before = copy_state_indexed_access();
+  compilation()->set_has_access_indexed(true);
+  Values* args = state()->pop_arguments(callee->arg_size());
+  Value array = args->at(0);
+  Value index = args->at(1);
+  if (is_store) {
+    Value value = args->at(2);
+    Instruction* store = append(new StoreIndexed(array, index, NULL, T_CHAR, value, state_before));
+    store->set_flag(Instruction::NeedsRangeCheckFlag, false);
+    _memory->store_value(value);
+  } else {
+    Instruction* load = append(new LoadIndexed(array, index, NULL, T_CHAR, state_before));
+    load->set_flag(Instruction::NeedsRangeCheckFlag, false);
+    push(load->type(), load);
+  }
+}
 
 void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) {
   CompileLog* log = compilation()->log();
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -372,6 +372,7 @@
   void append_unsafe_put_raw(ciMethod* callee, BasicType t);
   void append_unsafe_CAS(ciMethod* callee);
   void append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add);
+  void append_char_access(ciMethod* callee, bool is_store);
 
   void print_inlining(ciMethod* callee, const char* msg = NULL, bool success = true);
 
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -701,19 +701,22 @@
 LEAF(Local, Instruction)
  private:
   int      _java_index;                          // the local index within the method to which the local belongs
+  bool     _is_receiver;                         // if local variable holds the receiver: "this" for non-static methods
   ciType*  _declared_type;
  public:
   // creation
-  Local(ciType* declared, ValueType* type, int index)
+  Local(ciType* declared, ValueType* type, int index, bool receiver)
     : Instruction(type)
     , _java_index(index)
     , _declared_type(declared)
+    , _is_receiver(receiver)
   {
     NOT_PRODUCT(set_printable_bci(-1));
   }
 
   // accessors
   int java_index() const                         { return _java_index; }
+  bool is_receiver() const                       { return _is_receiver; }
 
   virtual ciType* declared_type() const          { return _declared_type; }
 
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -161,8 +161,6 @@
   // particular sparc uses this for delay slot filling.
   void peephole(LIR_List* list);
 
-  void emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst, CodeEmitInfo* info);
-
   void return_op(LIR_Opr result);
 
   // returns offset of poll instruction
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -3348,7 +3348,7 @@
 }
 
 void LIRGenerator::increment_event_counter(CodeEmitInfo* info, int bci, bool backedge) {
-  int freq_log;
+  int freq_log = 0;
   int level = compilation()->env()->comp_level();
   if (level == CompLevel_limited_profile) {
     freq_log = (backedge ? Tier2BackedgeNotifyFreqLog : Tier2InvokeNotifyFreqLog);
@@ -3394,7 +3394,7 @@
   assert(level > CompLevel_simple, "Shouldn't be here");
 
   int offset = -1;
-  LIR_Opr counter_holder;
+  LIR_Opr counter_holder = NULL;
   if (level == CompLevel_limited_profile) {
     MethodCounters* counters_adr = method->ensure_method_counters();
     if (counters_adr == NULL) {
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -414,7 +414,7 @@
   }
 
   static LIR_Condition lir_cond(If::Condition cond) {
-    LIR_Condition l;
+    LIR_Condition l = lir_cond_unknown;
     switch (cond) {
     case If::eql: l = lir_cond_equal;        break;
     case If::neq: l = lir_cond_notEqual;     break;
@@ -424,6 +424,7 @@
     case If::gtr: l = lir_cond_greater;      break;
     case If::aeq: l = lir_cond_aboveEqual;   break;
     case If::beq: l = lir_cond_belowEqual;   break;
+    default: fatal("You must pass valid If::Condition");
     };
     return l;
   }
--- a/hotspot/src/share/vm/ci/ciArrayKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciArrayKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
 //
 // Loaded array klass.
 ciArrayKlass::ciArrayKlass(KlassHandle h_k) : ciKlass(h_k) {
-  assert(get_Klass()->oop_is_array(), "wrong type");
+  assert(get_Klass()->is_array_klass(), "wrong type");
   _dimension = get_ArrayKlass()->dimension();
 }
 
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -366,11 +366,11 @@
     return true;
   }
 
-  if (resolved_klass->oop_is_objArray()) {
+  if (resolved_klass->is_objArray_klass()) {
     // Find the element klass, if this is an array.
     resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
   }
-  if (resolved_klass->oop_is_instance()) {
+  if (resolved_klass->is_instance_klass()) {
     return Reflection::verify_class_access(accessing_klass->get_Klass(),
                                            resolved_klass,
                                            true);
@@ -381,7 +381,7 @@
 // ------------------------------------------------------------------
 // ciEnv::get_klass_by_name_impl
 ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
-                                       constantPoolHandle cpool,
+                                       const constantPoolHandle& cpool,
                                        ciSymbol* name,
                                        bool require_local) {
   ASSERT_IN_VM;
@@ -503,7 +503,7 @@
 // ciEnv::get_klass_by_index_impl
 //
 // Implementation of get_klass_by_index.
-ciKlass* ciEnv::get_klass_by_index_impl(constantPoolHandle cpool,
+ciKlass* ciEnv::get_klass_by_index_impl(const constantPoolHandle& cpool,
                                         int index,
                                         bool& is_accessible,
                                         ciInstanceKlass* accessor) {
@@ -560,7 +560,7 @@
 // ciEnv::get_klass_by_index
 //
 // Get a klass from the constant pool.
-ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool,
+ciKlass* ciEnv::get_klass_by_index(const constantPoolHandle& cpool,
                                    int index,
                                    bool& is_accessible,
                                    ciInstanceKlass* accessor) {
@@ -571,7 +571,7 @@
 // ciEnv::get_constant_by_index_impl
 //
 // Implementation of get_constant_by_index().
-ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
+ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
                                              int pool_index, int cache_index,
                                              ciInstanceKlass* accessor) {
   bool ignore_will_link;
@@ -657,7 +657,7 @@
 // Pull a constant out of the constant pool.  How appropriate.
 //
 // Implementation note: this query is currently in no way cached.
-ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
+ciConstant ciEnv::get_constant_by_index(const constantPoolHandle& cpool,
                                         int pool_index, int cache_index,
                                         ciInstanceKlass* accessor) {
   GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, pool_index, cache_index, accessor);)
@@ -737,7 +737,7 @@
 
 // ------------------------------------------------------------------
 // ciEnv::get_method_by_index_impl
-ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
+ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
                                           int index, Bytecodes::Code bc,
                                           ciInstanceKlass* accessor) {
   if (bc == Bytecodes::_invokedynamic) {
@@ -849,7 +849,7 @@
 
 // ------------------------------------------------------------------
 // ciEnv::get_method_by_index
-ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
+ciMethod* ciEnv::get_method_by_index(const constantPoolHandle& cpool,
                                      int index, Bytecodes::Code bc,
                                      ciInstanceKlass* accessor) {
   GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);)
--- a/hotspot/src/share/vm/ci/ciEnv.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,34 +120,34 @@
                              bool require_local);
 
   // Constant pool access.
-  ciKlass*   get_klass_by_index(constantPoolHandle cpool,
+  ciKlass*   get_klass_by_index(const constantPoolHandle& cpool,
                                 int klass_index,
                                 bool& is_accessible,
                                 ciInstanceKlass* loading_klass);
-  ciConstant get_constant_by_index(constantPoolHandle cpool,
+  ciConstant get_constant_by_index(const constantPoolHandle& cpool,
                                    int pool_index, int cache_index,
                                    ciInstanceKlass* accessor);
   ciField*   get_field_by_index(ciInstanceKlass* loading_klass,
                                 int field_index);
-  ciMethod*  get_method_by_index(constantPoolHandle cpool,
+  ciMethod*  get_method_by_index(const constantPoolHandle& cpool,
                                  int method_index, Bytecodes::Code bc,
                                  ciInstanceKlass* loading_klass);
 
   // Implementation methods for loading and constant pool access.
   ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass,
-                                  constantPoolHandle cpool,
+                                  const constantPoolHandle& cpool,
                                   ciSymbol* klass_name,
                                   bool require_local);
-  ciKlass*   get_klass_by_index_impl(constantPoolHandle cpool,
+  ciKlass*   get_klass_by_index_impl(const constantPoolHandle& cpool,
                                      int klass_index,
                                      bool& is_accessible,
                                      ciInstanceKlass* loading_klass);
-  ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
+  ciConstant get_constant_by_index_impl(const constantPoolHandle& cpool,
                                         int pool_index, int cache_index,
                                         ciInstanceKlass* loading_klass);
   ciField*   get_field_by_index_impl(ciInstanceKlass* loading_klass,
                                      int field_index);
-  ciMethod*  get_method_by_index_impl(constantPoolHandle cpool,
+  ciMethod*  get_method_by_index_impl(const constantPoolHandle& cpool,
                                       int method_index, Bytecodes::Code bc,
                                       ciInstanceKlass* loading_klass);
 
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
 ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
   ciKlass(h_k)
 {
-  assert(get_Klass()->oop_is_instance(), "wrong type");
+  assert(get_Klass()->is_instance_klass(), "wrong type");
   assert(get_instanceKlass()->is_loaded(), "must be at least loaded");
   InstanceKlass* ik = get_instanceKlass();
 
@@ -356,7 +356,7 @@
   VM_ENTRY_MARK;
   InstanceKlass* ik = get_instanceKlass();
   Klass* up = ik->up_cast_abstract();
-  assert(up->oop_is_instance(), "must be InstanceKlass");
+  assert(up->is_instance_klass(), "must be InstanceKlass");
   if (ik == up) {
     return NULL;
   }
@@ -683,7 +683,7 @@
   // Try to record related loaded classes
   Klass* sub = ik->subklass();
   while (sub != NULL) {
-    if (sub->oop_is_instance()) {
+    if (sub->is_instance_klass()) {
       out->print_cr("instanceKlass %s", sub->name()->as_quoted_ascii());
     }
     sub = sub->next_sibling();
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,7 @@
   ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
 
   InstanceKlass* get_instanceKlass() const {
-    return (InstanceKlass*)get_Klass();
+    return InstanceKlass::cast(get_Klass());
   }
 
   oop loader();
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -744,7 +744,7 @@
 #ifndef PRODUCT
   if (TraceDependencies && target() != NULL && target() != root_m->get_Method()) {
     tty->print("found a non-root unique target method");
-    tty->print_cr("  context = %s", InstanceKlass::cast(actual_recv->get_Klass())->external_name());
+    tty->print_cr("  context = %s", actual_recv->get_Klass()->external_name());
     tty->print("  method  = ");
     target->print_short_name(tty);
     tty->cr();
@@ -790,7 +790,7 @@
    methodHandle m;
    // Only do exact lookup if receiver klass has been linked.  Otherwise,
    // the vtable has not been setup, and the LinkResolver will fail.
-   if (h_recv->oop_is_array()
+   if (h_recv->is_array_klass()
         ||
        InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) {
      if (holder()->is_interface()) {
--- a/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciObjArrayKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
 //
 // Constructor for loaded object array klasses.
 ciObjArrayKlass::ciObjArrayKlass(KlassHandle h_k) : ciArrayKlass(h_k) {
-  assert(get_Klass()->oop_is_objArray(), "wrong type");
+  assert(get_Klass()->is_objArray_klass(), "wrong type");
   Klass* element_Klass = get_ObjArrayKlass()->bottom_klass();
   _base_element_klass = CURRENT_ENV->get_klass(element_Klass);
   assert(_base_element_klass->is_instance_klass() ||
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -357,7 +357,7 @@
   // Hold metadata from unloading by keeping it's holder alive.
   if (_initialized && o->is_klass()) {
     Klass* holder = ((Klass*)o);
-    if (holder->oop_is_instance() && InstanceKlass::cast(holder)->is_anonymous()) {
+    if (holder->is_instance_klass() && InstanceKlass::cast(holder)->is_anonymous()) {
       // Though ciInstanceKlass records class loader oop, it's not enough to keep
       // VM anonymous classes alive (loader == NULL). Klass holder should be used instead.
       // It is enough to record a ciObject, since cached elements are never removed
@@ -370,11 +370,11 @@
   if (o->is_klass()) {
     KlassHandle h_k(THREAD, (Klass*)o);
     Klass* k = (Klass*)o;
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       return new (arena()) ciInstanceKlass(h_k);
-    } else if (k->oop_is_objArray()) {
+    } else if (k->is_objArray_klass()) {
       return new (arena()) ciObjArrayKlass(h_k);
-    } else if (k->oop_is_typeArray()) {
+    } else if (k->is_typeArray_klass()) {
       return new (arena()) ciTypeArrayKlass(h_k);
     }
   } else if (o->is_method()) {
@@ -414,6 +414,7 @@
     metadata_owner_klass = m->as_method()->get_Method()->constants()->pool_holder();
   } else {
     fatal("Not implemented for other types of metadata");
+    return;
   }
 
   oop metadata_holder = metadata_owner_klass->klass_holder();
--- a/hotspot/src/share/vm/ci/ciReplay.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciReplay.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -530,15 +530,15 @@
     if (_imethod != NULL) {
       return; // Replay Inlining
     }
-    Klass* k = method->method_holder();
-    ((InstanceKlass*)k)->initialize(THREAD);
+    InstanceKlass* ik = method->method_holder();
+    ik->initialize(THREAD);
     if (HAS_PENDING_EXCEPTION) {
       oop throwable = PENDING_EXCEPTION;
       java_lang_Throwable::print(throwable, tty);
       tty->cr();
       if (ReplayIgnoreInitErrors) {
         CLEAR_PENDING_EXCEPTION;
-        ((InstanceKlass*)k)->set_init_state(InstanceKlass::fully_initialized);
+        ik->set_init_state(InstanceKlass::fully_initialized);
       } else {
         return;
       }
@@ -842,7 +842,7 @@
       } else if (field_signature[0] == 'L') {
         Symbol* klass_name = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK);
         KlassHandle kelem = resolve_klass(field_signature, CHECK);
-        oop value = ((InstanceKlass*)kelem())->allocate_instance(CHECK);
+        oop value = InstanceKlass::cast(kelem())->allocate_instance(CHECK);
         java_mirror->obj_field_put(fd.offset(), value);
       } else {
         report_error("unhandled staticfield");
--- a/hotspot/src/share/vm/ci/ciSignature.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciSignature.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
 
 // ------------------------------------------------------------------
 // ciSignature::ciSignature
-ciSignature::ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* symbol) {
+ciSignature::ciSignature(ciKlass* accessing_klass, const constantPoolHandle& cpool, ciSymbol* symbol) {
   ASSERT_IN_VM;
   EXCEPTION_CONTEXT;
   _accessing_klass = accessing_klass;
--- a/hotspot/src/share/vm/ci/ciSignature.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciSignature.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
   friend class ciBytecodeStream;
   friend class ciObjectFactory;
 
-  ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature);
+  ciSignature(ciKlass* accessing_klass, const constantPoolHandle& cpool, ciSymbol* signature);
   ciSignature(ciKlass* accessing_klass,                           ciSymbol* signature, ciMethodType* method_type);
 
   void get_all_klasses();
--- a/hotspot/src/share/vm/ci/ciType.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciType.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,7 @@
 }
 
 ciType::ciType(KlassHandle k) : ciMetadata(k()) {
-  _basic_type = k()->oop_is_array() ? T_ARRAY : T_OBJECT;
+  _basic_type = k()->is_array_klass() ? T_ARRAY : T_OBJECT;
 }
 
 
--- a/hotspot/src/share/vm/ci/ciTypeArray.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciTypeArray.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,3 +46,13 @@
 #endif //ASSERT
   return c;
 }
+
+// ------------------------------------------------------------------
+// ciTypeArray::byte_at
+//
+// Implementation of the byte_at method.
+jbyte ciTypeArray::byte_at(int index) {
+  VM_ENTRY_MARK;
+  assert(index >= 0 && index < length(), "out of range");
+  return get_typeArrayOop()->byte_at(index);
+}
--- a/hotspot/src/share/vm/ci/ciTypeArray.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciTypeArray.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,6 +56,9 @@
   // array will never change.
   jchar char_at(int index);
 
+  // Return byte at index.
+  jbyte byte_at(int index);
+
 };
 
 #endif // SHARE_VM_CI_CITYPEARRAY_HPP
--- a/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/ci/ciTypeArrayKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 // ------------------------------------------------------------------
 // ciTypeArrayKlass::ciTypeArrayKlass
 ciTypeArrayKlass::ciTypeArrayKlass(KlassHandle h_k) : ciArrayKlass(h_k) {
-  assert(get_Klass()->oop_is_typeArray(), "wrong type");
+  assert(get_Klass()->is_typeArray_klass(), "wrong type");
   assert(element_type() == get_TypeArrayKlass()->element_type(), "");
 }
 
--- a/hotspot/src/share/vm/classfile/bytecodeAssembler.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/bytecodeAssembler.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,7 @@
   BytecodeCPEntry const& at(u2 index) const { return _entries.at(index); }
 
   InstanceKlass* pool_holder() const {
-    return InstanceKlass::cast(_orig->pool_holder());
+    return _orig->pool_holder();
   }
 
   u2 utf8(Symbol* sym) {
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -315,6 +315,7 @@
     return NULL;
 }
 
+#ifdef ASSERT
 PRAGMA_DIAG_PUSH
 PRAGMA_FORMAT_NONLITERAL_IGNORED
 void ClassFileParser::report_assert_property_failure(const char* msg, TRAPS) {
@@ -327,6 +328,7 @@
   fatal(msg, index, _class_name->as_C_string());
 }
 PRAGMA_DIAG_POP
+#endif
 
 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
   ClassFileStream* cfs = stream();
@@ -646,7 +648,7 @@
 }
 
 
-void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS) {
+void ClassFileParser::patch_constant_pool(const constantPoolHandle& cp, int index, Handle patch, TRAPS) {
   BasicType patch_type = T_VOID;
 
   switch (cp->tag_at(index).value()) {
@@ -822,7 +824,7 @@
       debug_only(No_Safepoint_Verifier nsv;)
       for (index = 0; index < length; index++) {
         Klass* k = _local_interfaces->at(index);
-        Symbol* name = InstanceKlass::cast(k)->name();
+        Symbol* name = k->name();
         // If no duplicates, add (name, NULL) in hashtable interface_names.
         if (!put_after_lookup(name, NULL, interface_names)) {
           dup = true;
@@ -3175,8 +3177,9 @@
     bool is_array = false;
     if (_cp->tag_at(super_class_index).is_klass()) {
       super_klass = instanceKlassHandle(THREAD, _cp->resolved_klass_at(super_class_index));
-      if (_need_verify)
-        is_array = super_klass->oop_is_array();
+      if (_need_verify) {
+        is_array = super_klass->is_array_klass();
+      }
     } else if (_need_verify) {
       is_array = (_cp->klass_name_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
     }
@@ -3211,19 +3214,19 @@
 
   // Field size and offset computation
   int nonstatic_field_size = _super_klass() == NULL ? 0 : _super_klass()->nonstatic_field_size();
-  int next_static_oop_offset;
-  int next_static_double_offset;
-  int next_static_word_offset;
-  int next_static_short_offset;
-  int next_static_byte_offset;
-  int next_nonstatic_oop_offset;
-  int next_nonstatic_double_offset;
-  int next_nonstatic_word_offset;
-  int next_nonstatic_short_offset;
-  int next_nonstatic_byte_offset;
-  int first_nonstatic_oop_offset;
-  int next_nonstatic_field_offset;
-  int next_nonstatic_padded_offset;
+  int next_static_oop_offset = 0;
+  int next_static_double_offset = 0;
+  int next_static_word_offset = 0;
+  int next_static_short_offset = 0;
+  int next_static_byte_offset = 0;
+  int next_nonstatic_oop_offset = 0;
+  int next_nonstatic_double_offset = 0;
+  int next_nonstatic_word_offset = 0;
+  int next_nonstatic_short_offset = 0;
+  int next_nonstatic_byte_offset = 0;
+  int first_nonstatic_oop_offset = 0;
+  int next_nonstatic_field_offset = 0;
+  int next_nonstatic_padded_offset = 0;
 
   // Count the contended fields by type.
   //
@@ -3376,14 +3379,14 @@
     ShouldNotReachHere();
   }
 
-  int nonstatic_oop_space_count   = 0;
-  int nonstatic_word_space_count  = 0;
-  int nonstatic_short_space_count = 0;
-  int nonstatic_byte_space_count  = 0;
-  int nonstatic_oop_space_offset;
-  int nonstatic_word_space_offset;
-  int nonstatic_short_space_offset;
-  int nonstatic_byte_space_offset;
+  int nonstatic_oop_space_count    = 0;
+  int nonstatic_word_space_count   = 0;
+  int nonstatic_short_space_count  = 0;
+  int nonstatic_byte_space_count   = 0;
+  int nonstatic_oop_space_offset   = 0;
+  int nonstatic_word_space_offset  = 0;
+  int nonstatic_short_space_offset = 0;
+  int nonstatic_byte_space_offset  = 0;
 
   // Try to squeeze some of the fields into the gaps due to
   // long/double alignment.
@@ -3455,7 +3458,7 @@
     // contended instance fields are handled below
     if (fs.is_contended() && !fs.access_flags().is_static()) continue;
 
-    int real_offset;
+    int real_offset = 0;
     FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
 
     // pack the rest of the fields
@@ -3589,7 +3592,7 @@
         // handle statics below
         if (fs.access_flags().is_static()) continue;
 
-        int real_offset;
+        int real_offset = 0;
         FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();
 
         switch (atype) {
@@ -4111,7 +4114,7 @@
     this_klass->set_should_verify_class(verify);
     jint lh = Klass::instance_layout_helper(info.instance_size, false);
     this_klass->set_layout_helper(lh);
-    assert(this_klass->oop_is_instance(), "layout is correct");
+    assert(this_klass->is_instance_klass(), "layout is correct");
     assert(this_klass->size_helper() == info.instance_size, "correct size_helper");
     // Not yet: supers are done below to support the new subtype-checking fields
     //this_klass->set_super(super_klass());
@@ -4315,13 +4318,13 @@
         if (caller != NULL) {
           tty->print("[Loaded %s by instance of %s]\n",
                      this_klass->external_name(),
-                     InstanceKlass::cast(caller)->external_name());
+                     caller->external_name());
         } else {
           tty->print("[Loaded %s]\n", this_klass->external_name());
         }
       } else {
         tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
-                   InstanceKlass::cast(class_loader->klass())->external_name());
+                   class_loader->klass()->external_name());
       }
     }
 
@@ -4330,7 +4333,7 @@
       // print out the superclass.
       const char * from = this_klass()->external_name();
       if (this_klass->java_super() != NULL) {
-        tty->print("RESOLVE %s %s (super)\n", from, InstanceKlass::cast(this_klass->java_super())->external_name());
+        tty->print("RESOLVE %s %s (super)\n", from, this_klass->java_super()->external_name());
       }
       // print out each of the interface classes referred to by this class.
       Array<Klass*>* local_interfaces = this_klass->local_interfaces();
@@ -4338,8 +4341,7 @@
         int length = local_interfaces->length();
         for (int i = 0; i < length; i++) {
           Klass* k = local_interfaces->at(i);
-          InstanceKlass* to_class = InstanceKlass::cast(k);
-          const char * to = to_class->external_name();
+          const char * to = k->external_name();
           tty->print("RESOLVE %s %s (interface)\n", from, to);
         }
       }
@@ -4411,7 +4413,7 @@
 
 void ClassFileParser::print_field_layout(Symbol* name,
                                          Array<u2>* fields,
-                                         constantPoolHandle cp,
+                                         const constantPoolHandle& cp,
                                          int instance_size,
                                          int instance_fields_start,
                                          int instance_fields_end,
@@ -4687,7 +4689,7 @@
       vmSymbols::java_lang_IllegalAccessError(),
       "class %s cannot access its superclass %s",
       this_klass->external_name(),
-      InstanceKlass::cast(super)->external_name()
+      super->external_name()
     );
     return;
   }
@@ -4707,7 +4709,7 @@
         vmSymbols::java_lang_IllegalAccessError(),
         "class %s cannot access its superinterface %s",
         this_klass->external_name(),
-        InstanceKlass::cast(k)->external_name()
+        k->external_name()
       );
       return;
     }
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -241,7 +241,7 @@
 
   void print_field_layout(Symbol* name,
                           Array<u2>* fields,
-                          constantPoolHandle cp,
+                          const constantPoolHandle& cp,
                           int instance_size,
                           int instance_fields_start,
                           int instance_fields_end,
@@ -319,8 +319,8 @@
     if (!b) { classfile_parse_error(msg, CHECK); }
   }
 
-  void report_assert_property_failure(const char* msg, TRAPS);
-  void report_assert_property_failure(const char* msg, int index, TRAPS);
+  void report_assert_property_failure(const char* msg, TRAPS) PRODUCT_RETURN;
+  void report_assert_property_failure(const char* msg, int index, TRAPS) PRODUCT_RETURN;
 
   inline void assert_property(bool b, const char* msg, TRAPS) {
 #ifdef ASSERT
@@ -403,7 +403,7 @@
     assert(!has_cp_patch_at(index), "");
     return patch;
   }
-  void patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS);
+  void patch_constant_pool(const constantPoolHandle& cp, int index, Handle patch, TRAPS);
 
   // Wrapper for constantTag.is_klass_[or_]reference.
   // In older versions of the VM, Klass*s cannot sneak into early phases of
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -140,7 +140,7 @@
 
 void ClassLoaderData::methods_do(void f(Method*)) {
   for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       InstanceKlass::cast(k)->methods_do(f);
     }
   }
@@ -151,7 +151,7 @@
   MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
   for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
     // Do not filter ArrayKlass oops here...
-    if (k->oop_is_array() || (k->oop_is_instance() && InstanceKlass::cast(k)->is_loaded())) {
+    if (k->is_array_klass() || (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded())) {
       klass_closure->do_klass(k);
     }
   }
@@ -159,7 +159,7 @@
 
 void ClassLoaderData::classes_do(void f(InstanceKlass*)) {
   for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       f(InstanceKlass::cast(k));
     }
     assert(k != k->next_link(), "no loops!");
--- a/hotspot/src/share/vm/classfile/compactHashtable.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -422,7 +422,7 @@
 
 int HashtableTextDump::scan_string_prefix() {
   // Expect /[0-9]+: /
-  int utf8_length;
+  int utf8_length = 0;
   get_num(':', &utf8_length);
   if (*_p != ' ') {
     corrupted(_p, "Wrong prefix format for string");
@@ -433,13 +433,13 @@
 
 int HashtableTextDump::scan_symbol_prefix() {
   // Expect /[0-9]+ (-|)[0-9]+: /
-  int utf8_length;
+  int utf8_length = 0;
   get_num(' ', &utf8_length);
-    if (*_p == '-') {
-     _p++;
+  if (*_p == '-') {
+    _p++;
   }
   int ref_num;
-  (void)get_num(':', &ref_num);
+  get_num(':', &ref_num);
   if (*_p != ' ') {
     corrupted(_p, "Wrong prefix format for symbol");
   }
--- a/hotspot/src/share/vm/classfile/dictionary.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +60,7 @@
   DictionaryEntry* entry = (DictionaryEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass);
   entry->set_loader_data(loader_data);
   entry->set_pd_set(NULL);
-  assert(klass->oop_is_instance(), "Must be");
+  assert(klass->is_instance_klass(), "Must be");
   return entry;
 }
 
@@ -78,7 +78,7 @@
 
 bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
 #ifdef ASSERT
-  if (protection_domain == InstanceKlass::cast(klass())->protection_domain()) {
+  if (protection_domain == klass()->protection_domain()) {
     // Ensure this doesn't show up in the pd_set (invariant)
     bool in_pd_set = false;
     for (ProtectionDomainEntry* current = _pd_set;
@@ -96,7 +96,7 @@
   }
 #endif /* ASSERT */
 
-  if (protection_domain == InstanceKlass::cast(klass())->protection_domain()) {
+  if (protection_domain == klass()->protection_domain()) {
     // Succeeds trivially
     return true;
   }
@@ -275,7 +275,7 @@
                           probe != NULL;
                           probe = probe->next()) {
       Klass* k = probe->klass();
-      if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) {
+      if (probe->loader_data() == k->class_loader_data()) {
         f(k);
       }
     }
@@ -290,7 +290,7 @@
                           probe != NULL;
                           probe = probe->next()) {
       Klass* k = probe->klass();
-      if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) {
+      if (probe->loader_data() == k->class_loader_data()) {
         f(k, CHECK);
       }
     }
@@ -322,7 +322,7 @@
                           probe != NULL;
                           probe = probe->next()) {
       Klass* k = probe->klass();
-      if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) {
+      if (probe->loader_data() == k->class_loader_data()) {
         // only take klass is we have the entry with the defining class loader
         InstanceKlass::cast(k)->methods_do(f);
       }
@@ -476,7 +476,7 @@
     DictionaryEntry* p = master_list;
     master_list = master_list->next();
     p->set_next(NULL);
-    Symbol* class_name = InstanceKlass::cast((Klass*)(p->klass()))->name();
+    Symbol* class_name = p->klass()->name();
     // Since the null class loader data isn't copied to the CDS archive,
     // compute the hash with NULL for loader data.
     unsigned int hash = compute_hash(class_name, NULL);
@@ -723,7 +723,7 @@
       Klass* e = probe->klass();
       ClassLoaderData* loader_data =  probe->loader_data();
       bool is_defining_class =
-         (loader_data == InstanceKlass::cast(e)->class_loader_data());
+         (loader_data == e->class_loader_data());
       tty->print("%s%s", ((!details) || is_defining_class) ? " " : "^",
                    e->external_name());
 
@@ -756,7 +756,7 @@
                           probe = probe->next()) {
       Klass* e = probe->klass();
       ClassLoaderData* loader_data = probe->loader_data();
-      guarantee(e->oop_is_instance(),
+      guarantee(e->is_instance_klass(),
                               "Verify of system dictionary failed");
       // class loader must be present;  a null class loader is the
       // boostrap loader
--- a/hotspot/src/share/vm/classfile/dictionary.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/dictionary.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -323,8 +323,7 @@
 
   bool equals(Symbol* class_name, ClassLoaderData* loader_data) const {
     Klass* klass = (Klass*)literal();
-    return (InstanceKlass::cast(klass)->name() == class_name &&
-            _loader_data == loader_data);
+    return (klass->name() == class_name && _loader_data == loader_data);
   }
 
   void print() {
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -114,17 +114,17 @@
 // Helpful routine for computing field offsets at run time rather than hardcoding them
 static void
 compute_offset(int &dest_offset,
-               Klass* klass_oop, Symbol* name_symbol, Symbol* signature_symbol,
+               Klass* klass, Symbol* name_symbol, Symbol* signature_symbol,
                bool is_static = false, bool allow_super = false) {
   fieldDescriptor fd;
-  InstanceKlass* ik = InstanceKlass::cast(klass_oop);
+  InstanceKlass* ik = InstanceKlass::cast(klass);
   if (!find_field(ik, name_symbol, signature_symbol, &fd, is_static, allow_super)) {
     ResourceMark rm;
     tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
 #ifndef PRODUCT
-    klass_oop->print();
+    ik->print();
     tty->print_cr("all fields:");
-    for (AllFieldStream fs(InstanceKlass::cast(klass_oop)); !fs.done(); fs.next()) {
+    for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
       tty->print_cr("  name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int());
     }
 #endif //PRODUCT
@@ -136,10 +136,10 @@
 // Same as above but for "optional" offsets that might not be present in certain JDK versions
 static void
 compute_optional_offset(int& dest_offset,
-                        Klass* klass_oop, Symbol* name_symbol, Symbol* signature_symbol,
+                        Klass* klass, Symbol* name_symbol, Symbol* signature_symbol,
                         bool allow_super = false) {
   fieldDescriptor fd;
-  InstanceKlass* ik = InstanceKlass::cast(klass_oop);
+  InstanceKlass* ik = InstanceKlass::cast(klass);
   if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
     dest_offset = fd.offset();
   }
@@ -147,9 +147,8 @@
 
 
 int java_lang_String::value_offset  = 0;
-int java_lang_String::offset_offset = 0;
-int java_lang_String::count_offset  = 0;
 int java_lang_String::hash_offset   = 0;
+int java_lang_String::coder_offset  = 0;
 
 bool java_lang_String::initialized  = false;
 
@@ -161,44 +160,85 @@
   assert(!initialized, "offsets should be initialized only once");
 
   Klass* k = SystemDictionary::String_klass();
-  compute_offset(value_offset,           k, vmSymbols::value_name(),  vmSymbols::char_array_signature());
-  compute_optional_offset(offset_offset, k, vmSymbols::offset_name(), vmSymbols::int_signature());
-  compute_optional_offset(count_offset,  k, vmSymbols::count_name(),  vmSymbols::int_signature());
+  compute_offset(value_offset,           k, vmSymbols::value_name(),  vmSymbols::byte_array_signature());
   compute_optional_offset(hash_offset,   k, vmSymbols::hash_name(),   vmSymbols::int_signature());
+  compute_optional_offset(coder_offset,  k, vmSymbols::coder_name(),  vmSymbols::byte_signature());
 
   initialized = true;
 }
 
-Handle java_lang_String::basic_create(int length, TRAPS) {
+class CompactStringsFixup : public FieldClosure {
+private:
+  bool _value;
+
+public:
+  CompactStringsFixup(bool value) : _value(value) {}
+
+  void do_field(fieldDescriptor* fd) {
+    if (fd->name() == vmSymbols::compact_strings_name()) {
+      oop mirror = fd->field_holder()->java_mirror();
+      assert(fd->field_holder() == SystemDictionary::String_klass(), "Should be String");
+      assert(mirror != NULL, "String must have mirror already");
+      mirror->bool_field_put(fd->offset(), _value);
+    }
+  }
+};
+
+void java_lang_String::set_compact_strings(bool value) {
+  CompactStringsFixup fix(value);
+  InstanceKlass::cast(SystemDictionary::String_klass())->do_local_static_fields(&fix);
+}
+
+Handle java_lang_String::basic_create(int length, bool is_latin1, TRAPS) {
   assert(initialized, "Must be initialized");
+  assert(CompactStrings || !is_latin1, "Must be UTF16 without CompactStrings");
+
   // Create the String object first, so there's a chance that the String
   // and the char array it points to end up in the same cache line.
   oop obj;
-  obj = InstanceKlass::cast(SystemDictionary::String_klass())->allocate_instance(CHECK_NH);
+  obj = SystemDictionary::String_klass()->allocate_instance(CHECK_NH);
 
   // Create the char array.  The String object must be handlized here
   // because GC can happen as a result of the allocation attempt.
   Handle h_obj(THREAD, obj);
-  typeArrayOop buffer;
-    buffer = oopFactory::new_charArray(length, CHECK_NH);
+  int arr_length = is_latin1 ? length : length << 1; // 2 bytes per UTF16.
+  typeArrayOop buffer = oopFactory::new_byteArray(arr_length, CHECK_NH);;
 
   // Point the String at the char array
   obj = h_obj();
   set_value(obj, buffer);
   // No need to zero the offset, allocation zero'ed the entire String object
-  assert(offset(obj) == 0, "initial String offset should be zero");
-//set_offset(obj, 0);
-  set_count(obj, length);
-
+  set_coder(obj, is_latin1 ? CODER_LATIN1 : CODER_UTF16);
   return h_obj;
 }
 
 Handle java_lang_String::create_from_unicode(jchar* unicode, int length, TRAPS) {
-  Handle h_obj = basic_create(length, CHECK_NH);
+  bool is_latin1 = CompactStrings && UNICODE::is_latin1(unicode, length);
+  Handle h_obj = basic_create(length, is_latin1, CHECK_NH);
   typeArrayOop buffer = value(h_obj());
-  for (int index = 0; index < length; index++) {
-    buffer->char_at_put(index, unicode[index]);
+  assert(TypeArrayKlass::cast(buffer->klass())->element_type() == T_BYTE, "only byte[]");
+  if (is_latin1) {
+    for (int index = 0; index < length; index++) {
+      buffer->byte_at_put(index, (jbyte)unicode[index]);
+    }
+  } else {
+    for (int index = 0; index < length; index++) {
+      buffer->char_at_put(index, unicode[index]);
+    }
   }
+
+#ifdef ASSERT
+  {
+    ResourceMark rm;
+    char* expected = UNICODE::as_utf8(unicode, length);
+    char* actual = as_utf8_string(h_obj());
+    if (strcmp(expected, actual) != 0) {
+      tty->print_cr("Unicode conversion failure: %s --> %s", expected, actual);
+      ShouldNotReachHere();
+    }
+  }
+#endif
+
   return h_obj;
 }
 
@@ -211,11 +251,40 @@
   if (utf8_str == NULL) {
     return Handle();
   }
-  int length = UTF8::unicode_length(utf8_str);
-  Handle h_obj = basic_create(length, CHECK_NH);
+  bool has_multibyte, is_latin1;
+  int length = UTF8::unicode_length(utf8_str, is_latin1, has_multibyte);
+  if (!CompactStrings) {
+    has_multibyte = true;
+    is_latin1 = false;
+  }
+
+  Handle h_obj = basic_create(length, is_latin1, CHECK_NH);
   if (length > 0) {
-    UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length);
+    if (!has_multibyte) {
+      strncpy((char*)value(h_obj())->byte_at_addr(0), utf8_str, length);
+    } else if (is_latin1) {
+      UTF8::convert_to_unicode(utf8_str, value(h_obj())->byte_at_addr(0), length);
+    } else {
+      UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length);
+    }
   }
+
+#ifdef ASSERT
+  // This check is too strict because the input string is not necessarily valid UTF8.
+  // For example, it may be created with arbitrary content via jni_NewStringUTF.
+  /*
+  {
+    ResourceMark rm;
+    const char* expected = utf8_str;
+    char* actual = as_utf8_string(h_obj());
+    if (strcmp(expected, actual) != 0) {
+      tty->print_cr("String conversion failure: %s --> %s", expected, actual);
+      ShouldNotReachHere();
+    }
+  }
+  */
+#endif
+
   return h_obj;
 }
 
@@ -225,11 +294,39 @@
 }
 
 Handle java_lang_String::create_from_symbol(Symbol* symbol, TRAPS) {
-  int length = UTF8::unicode_length((char*)symbol->bytes(), symbol->utf8_length());
-  Handle h_obj = basic_create(length, CHECK_NH);
+  const char* utf8_str = (char*)symbol->bytes();
+  int utf8_len = symbol->utf8_length();
+
+  bool has_multibyte, is_latin1;
+  int length = UTF8::unicode_length(utf8_str, utf8_len, is_latin1, has_multibyte);
+  if (!CompactStrings) {
+    has_multibyte = true;
+    is_latin1 = false;
+  }
+
+  Handle h_obj = basic_create(length, is_latin1, CHECK_NH);
   if (length > 0) {
-    UTF8::convert_to_unicode((char*)symbol->bytes(), value(h_obj())->char_at_addr(0), length);
+    if (!has_multibyte) {
+      strncpy((char*)value(h_obj())->byte_at_addr(0), utf8_str, length);
+    } else if (is_latin1) {
+      UTF8::convert_to_unicode(utf8_str, value(h_obj())->byte_at_addr(0), length);
+    } else {
+      UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length);
+    }
   }
+
+#ifdef ASSERT
+  {
+    ResourceMark rm;
+    const char* expected = symbol->as_utf8();
+    char* actual = as_utf8_string(h_obj());
+    if (strncmp(expected, actual, utf8_len) != 0) {
+      tty->print_cr("Symbol conversion failure: %s --> %s", expected, actual);
+      ShouldNotReachHere();
+    }
+  }
+#endif
+
   return h_obj;
 }
 
@@ -261,7 +358,6 @@
 // Converts a Java String to a native C string that can be used for
 // native OS calls.
 char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) {
-
   typedef char* (*to_platform_string_fn_t)(JNIEnv*, jstring, bool*);
   static to_platform_string_fn_t _to_platform_string_fn = NULL;
 
@@ -292,13 +388,15 @@
   oop          obj    = java_string();
   // Typical usage is to convert all '/' to '.' in string.
   typeArrayOop value  = java_lang_String::value(obj);
-  int          offset = java_lang_String::offset(obj);
   int          length = java_lang_String::length(obj);
+  bool      is_latin1 = java_lang_String::is_latin1(obj);
 
   // First check if any from_char exist
   int index; // Declared outside, used later
   for (index = 0; index < length; index++) {
-    if (value->char_at(index + offset) == from_char) {
+    jchar c = !is_latin1 ? value->char_at(index) :
+                  ((jchar) value->byte_at(index)) & 0xff;
+    if (c == from_char) {
       break;
     }
   }
@@ -307,34 +405,66 @@
     return java_string;
   }
 
-  // Create new UNICODE buffer. Must handlize value because GC
+  // Check if result string will be latin1
+  bool to_is_latin1 = false;
+
+  // Replacement char must be latin1
+  if (CompactStrings && UNICODE::is_latin1(to_char)) {
+    if (is_latin1) {
+      // Source string is latin1 as well
+      to_is_latin1 = true;
+    } else if (!UNICODE::is_latin1(from_char)) {
+      // We are replacing an UTF16 char. Scan string to
+      // check if result can be latin1 encoded.
+      to_is_latin1 = true;
+      for (index = 0; index < length; index++) {
+        jchar c = value->char_at(index);
+        if (c != from_char && !UNICODE::is_latin1(c)) {
+          to_is_latin1 = false;
+          break;
+        }
+      }
+    }
+  }
+
+  // Create new UNICODE (or byte) buffer. Must handlize value because GC
   // may happen during String and char array creation.
   typeArrayHandle h_value(THREAD, value);
-  Handle string = basic_create(length, CHECK_NH);
-
+  Handle string = basic_create(length, to_is_latin1, CHECK_NH);
   typeArrayOop from_buffer = h_value();
-  typeArrayOop to_buffer   = java_lang_String::value(string());
+  typeArrayOop to_buffer = java_lang_String::value(string());
 
   // Copy contents
   for (index = 0; index < length; index++) {
-    jchar c = from_buffer->char_at(index + offset);
+    jchar c = (!is_latin1) ? from_buffer->char_at(index) :
+                    ((jchar) from_buffer->byte_at(index)) & 0xff;
     if (c == from_char) {
       c = to_char;
     }
-    to_buffer->char_at_put(index, c);
+    if (!to_is_latin1) {
+      to_buffer->char_at_put(index, c);
+    } else {
+      to_buffer->byte_at_put(index, (jbyte) c);
+    }
   }
   return string;
 }
 
 jchar* java_lang_String::as_unicode_string(oop java_string, int& length, TRAPS) {
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
                length = java_lang_String::length(java_string);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
 
   jchar* result = NEW_RESOURCE_ARRAY_RETURN_NULL(jchar, length);
   if (result != NULL) {
-    for (int index = 0; index < length; index++) {
-      result[index] = value->char_at(index + offset);
+    if (!is_latin1) {
+      for (int index = 0; index < length; index++) {
+        result[index] = value->char_at(index);
+      }
+    } else {
+      for (int index = 0; index < length; index++) {
+        result[index] = ((jchar) value->byte_at(index)) & 0xff;
+      }
     }
   } else {
     THROW_MSG_0(vmSymbols::java_lang_OutOfMemoryError(), "could not allocate Unicode string");
@@ -348,21 +478,35 @@
   if (length == 0) return 0;
 
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
-  return java_lang_String::hash_code(value->char_at_addr(offset), length);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+
+  if (is_latin1) {
+    return java_lang_String::hash_code(value->byte_at_addr(0), length);
+  } else {
+    return java_lang_String::hash_code(value->char_at_addr(0), length);
+  }
 }
 
 char* java_lang_String::as_quoted_ascii(oop java_string) {
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
-
-  jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
-  if (base == NULL) return NULL;
-
-  int result_length = UNICODE::quoted_ascii_length(base, length) + 1;
-  char* result = NEW_RESOURCE_ARRAY(char, result_length);
-  UNICODE::as_quoted_ascii(base, length, result, result_length);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+
+  if (length == 0) return NULL;
+
+  char* result;
+  int result_length;
+  if (!is_latin1) {
+    jchar* base = value->char_at_addr(0);
+    result_length = UNICODE::quoted_ascii_length(base, length) + 1;
+    result = NEW_RESOURCE_ARRAY(char, result_length);
+    UNICODE::as_quoted_ascii(base, length, result, result_length);
+  } else {
+    jbyte* base = value->byte_at_addr(0);
+    result_length = UNICODE::quoted_ascii_length(base, length) + 1;
+    result = NEW_RESOURCE_ARRAY(char, result_length);
+    UNICODE::as_quoted_ascii(base, length, result, result_length);
+  }
   assert(result_length >= length + 1, "must not be shorter");
   assert(result_length == (int)strlen(result) + 1, "must match");
   return result;
@@ -370,89 +514,141 @@
 
 unsigned int java_lang_String::hash_string(oop java_string) {
   int          length = java_lang_String::length(java_string);
-  // Zero length string doesn't hash necessarily hash to zero.
+  // Zero length string doesn't necessarily hash to zero.
   if (length == 0) {
-    return StringTable::hash_string(NULL, 0);
+    return StringTable::hash_string((jchar*) NULL, 0);
   }
 
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
-  return StringTable::hash_string(value->char_at_addr(offset), length);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  if (is_latin1) {
+    return StringTable::hash_string(value->byte_at_addr(0), length);
+  } else {
+    return StringTable::hash_string(value->char_at_addr(0), length);
+  }
 }
 
 Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) {
   oop          obj    = java_string();
   typeArrayOop value  = java_lang_String::value(obj);
-  int          offset = java_lang_String::offset(obj);
   int          length = java_lang_String::length(obj);
-  jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
-  Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD);
-  return sym;
+  bool      is_latin1 = java_lang_String::is_latin1(obj);
+  if (!is_latin1) {
+    jchar* base = (length == 0) ? NULL : value->char_at_addr(0);
+    Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD);
+    return sym;
+  } else {
+    ResourceMark rm;
+    jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0);
+    const char* base = UNICODE::as_utf8(position, length);
+    Symbol* sym = SymbolTable::lookup(base, length, THREAD);
+    return sym;
+  }
 }
 
 Symbol* java_lang_String::as_symbol_or_null(oop java_string) {
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
-  jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
-  return SymbolTable::probe_unicode(base, length);
-}
-
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  if (!is_latin1) {
+    jchar* base = (length == 0) ? NULL : value->char_at_addr(0);
+    return SymbolTable::probe_unicode(base, length);
+  } else {
+    ResourceMark rm;
+    jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0);
+    const char* base = UNICODE::as_utf8(position, length);
+    return SymbolTable::probe(base, length);
+  }
+}
 
 int java_lang_String::utf8_length(oop java_string) {
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
-  jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
-  return UNICODE::utf8_length(position, length);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  if (length == 0) {
+    return 0;
+  }
+  if (!is_latin1) {
+    return UNICODE::utf8_length(value->char_at_addr(0), length);
+  } else {
+    return UNICODE::utf8_length(value->byte_at_addr(0), length);
+  }
 }
 
 char* java_lang_String::as_utf8_string(oop java_string) {
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
-  jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
-  return UNICODE::as_utf8(position, length);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  if (!is_latin1) {
+    jchar* position = (length == 0) ? NULL : value->char_at_addr(0);
+    return UNICODE::as_utf8(position, length);
+  } else {
+    jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0);
+    return UNICODE::as_utf8(position, length);
+  }
 }
 
 char* java_lang_String::as_utf8_string(oop java_string, char* buf, int buflen) {
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
-  jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
-  return UNICODE::as_utf8(position, length, buf, buflen);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  if (!is_latin1) {
+    jchar* position = (length == 0) ? NULL : value->char_at_addr(0);
+    return UNICODE::as_utf8(position, length, buf, buflen);
+  } else {
+    jbyte* position = (length == 0) ? NULL : value->byte_at_addr(0);
+    return UNICODE::as_utf8(position, length, buf, buflen);
+  }
 }
 
 char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
   assert(start + len <= length, "just checking");
-  jchar* position = value->char_at_addr(offset + start);
-  return UNICODE::as_utf8(position, len);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  if (!is_latin1) {
+    jchar* position = value->char_at_addr(start);
+    return UNICODE::as_utf8(position, len);
+  } else {
+    jbyte* position = value->byte_at_addr(start);
+    return UNICODE::as_utf8(position, len);
+  }
 }
 
 char* java_lang_String::as_utf8_string(oop java_string, int start, int len, char* buf, int buflen) {
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
   assert(start + len <= length, "just checking");
-  jchar* position = value->char_at_addr(offset + start);
-  return UNICODE::as_utf8(position, len, buf, buflen);
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  if (!is_latin1) {
+    jchar* position = value->char_at_addr(start);
+    return UNICODE::as_utf8(position, len, buf, buflen);
+  } else {
+    jbyte* position = value->byte_at_addr(start);
+    return UNICODE::as_utf8(position, len, buf, buflen);
+  }
 }
 
 bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
   assert(java_string->klass() == SystemDictionary::String_klass(),
          "must be java_string");
   typeArrayOop value  = java_lang_String::value(java_string);
-  int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
   if (length != len) {
     return false;
   }
-  for (int i = 0; i < len; i++) {
-    if (value->char_at(i + offset) != chars[i]) {
-      return false;
+  bool      is_latin1 = java_lang_String::is_latin1(java_string);
+  if (!is_latin1) {
+    for (int i = 0; i < len; i++) {
+      if (value->char_at(i) != chars[i]) {
+        return false;
+      }
+    }
+  } else {
+    for (int i = 0; i < len; i++) {
+      if ((((jchar) value->byte_at(i)) & 0xff) != chars[i]) {
+        return false;
+      }
     }
   }
   return true;
@@ -464,17 +660,20 @@
   assert(str2->klass() == SystemDictionary::String_klass(),
          "must be java String");
   typeArrayOop value1  = java_lang_String::value(str1);
-  int          offset1 = java_lang_String::offset(str1);
   int          length1 = java_lang_String::length(str1);
+  bool       is_latin1 = java_lang_String::is_latin1(str1);
   typeArrayOop value2  = java_lang_String::value(str2);
-  int          offset2 = java_lang_String::offset(str2);
   int          length2 = java_lang_String::length(str2);
-
-  if (length1 != length2) {
+  bool       is_latin2 = java_lang_String::is_latin1(str2);
+
+  if ((length1 != length2) || (is_latin1 != is_latin2)) {
+    // Strings of different size or with different
+    // coders are never equal.
     return false;
   }
-  for (int i = 0; i < length1; i++) {
-    if (value1->char_at(i + offset1) != value2->char_at(i + offset2)) {
+  int blength1 = value1->length();
+  for (int i = 0; i < value1->length(); i++) {
+    if (value1->byte_at(i) != value2->byte_at(i)) {
       return false;
     }
   }
@@ -492,12 +691,13 @@
     return;
   }
 
-  int offset = java_lang_String::offset(java_string);
   int length = java_lang_String::length(java_string);
+  bool is_latin1 = java_lang_String::is_latin1(java_string);
 
   st->print("\"");
   for (int index = 0; index < length; index++) {
-    st->print("%c", value->char_at(index + offset));
+    st->print("%c", (!is_latin1) ?  value->char_at(index) :
+                           ((jchar) value->byte_at(index)) & 0xff );
   }
   st->print("\"");
 }
@@ -555,7 +755,7 @@
 
   // If the offset was read from the shared archive, it was fixed up already
   if (!k->is_shared()) {
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       // During bootstrap, java.lang.Class wasn't loaded so static field
       // offsets were computed without the size added it.  Go back and
       // update all the static field offsets to included the size.
@@ -613,13 +813,13 @@
     java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror()));
 
     // It might also have a component mirror.  This mirror must already exist.
-    if (k->oop_is_array()) {
+    if (k->is_array_klass()) {
       Handle comp_mirror;
-      if (k->oop_is_typeArray()) {
+      if (k->is_typeArray_klass()) {
         BasicType type = TypeArrayKlass::cast(k())->element_type();
         comp_mirror = Universe::java_mirror(type);
       } else {
-        assert(k->oop_is_objArray(), "Must be");
+        assert(k->is_objArray_klass(), "Must be");
         Klass* element_klass = ObjArrayKlass::cast(k())->element_klass();
         assert(element_klass != NULL, "Must have an element klass");
         comp_mirror = element_klass->java_mirror();
@@ -631,7 +831,7 @@
       set_component_mirror(mirror(), comp_mirror());
       set_array_klass(comp_mirror(), k());
     } else {
-      assert(k->oop_is_instance(), "Must be");
+      assert(k->is_instance_klass(), "Must be");
 
       initialize_mirror_fields(k, mirror, protection_domain, THREAD);
       if (HAS_PENDING_EXCEPTION) {
@@ -770,7 +970,7 @@
     name = vmSymbols::type_signature(primitive_type(java_class));
   } else {
     Klass* k = as_Klass(java_class);
-    is_instance = k->oop_is_instance();
+    is_instance = k->is_instance_klass();
     name = k->name();
   }
   if (name == NULL) {
@@ -793,7 +993,7 @@
     name->increment_refcount();
   } else {
     Klass* k = as_Klass(java_class);
-    if (!k->oop_is_instance()) {
+    if (!k->is_instance_klass()) {
       name = k->name();
       name->increment_refcount();
     } else {
@@ -829,13 +1029,13 @@
 
 Klass* java_lang_Class::array_klass(oop java_class) {
   Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset));
-  assert(k == NULL || k->is_klass() && k->oop_is_array(), "should be array klass");
+  assert(k == NULL || k->is_klass() && k->is_array_klass(), "should be array klass");
   return k;
 }
 
 
 void java_lang_Class::set_array_klass(oop java_class, Klass* klass) {
-  assert(klass->is_klass() && klass->oop_is_array(), "should be array klass");
+  assert(klass->is_klass() && klass->is_array_klass(), "should be array klass");
   java_class->metadata_field_put(_array_klass_offset, klass);
 }
 
@@ -1169,10 +1369,13 @@
 
 // ("name as oop" accessor is not necessary)
 
-typeArrayOop java_lang_ThreadGroup::name(oop java_thread_group) {
+const char* java_lang_ThreadGroup::name(oop java_thread_group) {
   oop name = java_thread_group->obj_field(_name_offset);
   // ThreadGroup.name can be null
-  return name == NULL ? (typeArrayOop)NULL : java_lang_String::value(name);
+  if (name != NULL) {
+    return java_lang_String::as_utf8_string(name);
+  }
+  return NULL;
 }
 
 int java_lang_ThreadGroup::nthreads(oop java_thread_group) {
@@ -1236,7 +1439,7 @@
 }
 
 oop java_lang_Throwable::unassigned_stacktrace() {
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Throwable_klass());
+  InstanceKlass* ik = SystemDictionary::Throwable_klass();
   address addr = ik->static_field_addr(static_unassigned_stacktrace_offset);
   if (UseCompressedOops) {
     return oopDesc::load_decode_heap_oop((narrowOop *)addr);
@@ -1293,7 +1496,7 @@
   ResourceMark rm;
   Klass* k = throwable->klass();
   assert(k != NULL, "just checking");
-  st->print("%s", InstanceKlass::cast(k)->external_name());
+  st->print("%s", k->external_name());
   oop msg = message(throwable);
   if (msg != NULL) {
     st->print(": %s", java_lang_String::as_utf8_string(msg));
@@ -1305,7 +1508,7 @@
   ResourceMark rm;
   Klass* k = throwable->klass();
   assert(k != NULL, "just checking");
-  st->print("%s", InstanceKlass::cast(k)->external_name());
+  st->print("%s", k->external_name());
   oop msg = message(throwable);
   if (msg != NULL) {
     st->print(": %s", java_lang_String::as_utf8_string(msg));
@@ -1561,7 +1764,7 @@
   st->print_cr("%s", buf);
 }
 
-void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) {
+void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) {
   Handle mirror = method->method_holder()->java_mirror();
   int method_id = method->orig_method_idnum();
   int version = method->constants()->version();
@@ -1632,7 +1835,7 @@
   }
 }
 
-void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS) {
+void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHandle& method, TRAPS) {
   if (!StackTraceInThrowable) return;
   ResourceMark rm(THREAD);
 
@@ -1763,7 +1966,7 @@
   set_backtrace(throwable(), bt.backtrace());
 }
 
-void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method) {
+void java_lang_Throwable::fill_in_stack_trace(Handle throwable, const methodHandle& method) {
   // No-op if stack trace is disabled
   if (!StackTraceInThrowable) {
     return;
@@ -1945,7 +2148,7 @@
   return element();
 }
 
-oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
+oop java_lang_StackTraceElement::create(const methodHandle& method, int bci, TRAPS) {
   Handle mirror (THREAD, method->method_holder()->java_mirror());
   int method_id = method->orig_method_idnum();
   int cpref = method->name_index();
@@ -2506,7 +2709,7 @@
 
   oop mirror = reflect->obj_field(_oop_offset);
   Klass* k = java_lang_Class::as_Klass(mirror);
-  assert(k->oop_is_instance(), "Must be");
+  assert(k->is_instance_klass(), "Must be");
 
   // Get the constant pool back from the klass.  Since class redefinition
   // merges the new constant pool into the old, this is essentially the
@@ -2663,13 +2866,13 @@
 
 // Support for java_lang_ref_Reference
 HeapWord *java_lang_ref_Reference::pending_list_lock_addr() {
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Reference_klass());
+  InstanceKlass* ik = SystemDictionary::Reference_klass();
   address addr = ik->static_field_addr(static_lock_offset);
   return (HeapWord*) addr;
 }
 
 oop java_lang_ref_Reference::pending_list_lock() {
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Reference_klass());
+  InstanceKlass* ik = SystemDictionary::Reference_klass();
   address addr = ik->static_field_addr(static_lock_offset);
   if (UseCompressedOops) {
     return oopDesc::load_decode_heap_oop((narrowOop *)addr);
@@ -2679,7 +2882,7 @@
 }
 
 HeapWord *java_lang_ref_Reference::pending_list_addr() {
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Reference_klass());
+  InstanceKlass* ik = SystemDictionary::Reference_klass();
   address addr = ik->static_field_addr(static_pending_offset);
   // XXX This might not be HeapWord aligned, almost rather be char *.
   return (HeapWord*)addr;
@@ -2702,13 +2905,13 @@
 }
 
 jlong java_lang_ref_SoftReference::clock() {
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::SoftReference_klass());
+  InstanceKlass* ik = SystemDictionary::SoftReference_klass();
   jlong* offset = (jlong*)ik->static_field_addr(static_clock_offset);
   return *offset;
 }
 
 void java_lang_ref_SoftReference::set_clock(jlong value) {
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::SoftReference_klass());
+  InstanceKlass* ik = SystemDictionary::SoftReference_klass();
   jlong* offset = (jlong*)ik->static_field_addr(static_clock_offset);
   *offset = value;
 }
@@ -3033,7 +3236,7 @@
 void java_security_AccessControlContext::compute_offsets() {
   assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
   fieldDescriptor fd;
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::AccessControlContext_klass());
+  InstanceKlass* ik = SystemDictionary::AccessControlContext_klass();
 
   if (!ik->find_local_field(vmSymbols::context_name(), vmSymbols::protectiondomain_signature(), &fd)) {
     fatal("Invalid layout of java.security.AccessControlContext");
@@ -3066,9 +3269,9 @@
 oop java_security_AccessControlContext::create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS) {
   assert(_isPrivileged_offset != 0, "offsets should have been initialized");
   // Ensure klass is initialized
-  InstanceKlass::cast(SystemDictionary::AccessControlContext_klass())->initialize(CHECK_0);
+  SystemDictionary::AccessControlContext_klass()->initialize(CHECK_0);
   // Allocate result
-  oop result = InstanceKlass::cast(SystemDictionary::AccessControlContext_klass())->allocate_instance(CHECK_0);
+  oop result = SystemDictionary::AccessControlContext_klass()->allocate_instance(CHECK_0);
   // Fill in values
   result->obj_field_put(_context_offset, context());
   result->obj_field_put(_privilegedContext_offset, privileged_context());
@@ -3190,7 +3393,7 @@
 
 
 bool java_lang_System::has_security_manager() {
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::System_klass());
+  InstanceKlass* ik = SystemDictionary::System_klass();
   address addr = ik->static_field_addr(static_security_offset);
   if (UseCompressedOops) {
     return oopDesc::load_decode_heap_oop((narrowOop *)addr) != NULL;
@@ -3541,14 +3744,13 @@
 
   // java.lang.String
 
-  CHECK_OFFSET("java/lang/String", java_lang_String, value, "[C");
-  if (java_lang_String::has_offset_field()) {
-    CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I");
-    CHECK_OFFSET("java/lang/String", java_lang_String, count, "I");
-  }
+  CHECK_OFFSET("java/lang/String", java_lang_String, value, "[B");
   if (java_lang_String::has_hash_field()) {
     CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
   }
+  if (java_lang_String::has_coder_field()) {
+    CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
+  }
 
   // java.lang.Class
 
@@ -3630,8 +3832,8 @@
 #endif // PRODUCT
 
 int InjectedField::compute_offset() {
-  Klass* klass_oop = klass();
-  for (AllFieldStream fs(InstanceKlass::cast(klass_oop)); !fs.done(); fs.next()) {
+  InstanceKlass* ik = InstanceKlass::cast(klass());
+  for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
     if (!may_be_java && !fs.access_flags().is_internal()) {
       // Only look at injected fields
       continue;
@@ -3641,11 +3843,11 @@
     }
   }
   ResourceMark rm;
-  tty->print_cr("Invalid layout of %s at %s/%s%s", InstanceKlass::cast(klass_oop)->external_name(), name()->as_C_string(), signature()->as_C_string(), may_be_java ? " (may_be_java)" : "");
+  tty->print_cr("Invalid layout of %s at %s/%s%s", ik->external_name(), name()->as_C_string(), signature()->as_C_string(), may_be_java ? " (may_be_java)" : "");
 #ifndef PRODUCT
-  klass_oop->print();
+  ik->print();
   tty->print_cr("all fields:");
-  for (AllFieldStream fs(InstanceKlass::cast(klass_oop)); !fs.done(); fs.next()) {
+  for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
     tty->print_cr("  name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int());
   }
 #endif //PRODUCT
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -53,28 +53,28 @@
 class java_lang_String : AllStatic {
  private:
   static int value_offset;
-  static int offset_offset;
-  static int count_offset;
   static int hash_offset;
+  static int coder_offset;
 
   static bool initialized;
 
-  static Handle basic_create(int length, TRAPS);
+  static Handle basic_create(int length, bool byte_arr, TRAPS);
 
-  static void set_offset(oop string, int offset) {
+  static void set_coder(oop string, jbyte coder) {
     assert(initialized, "Must be initialized");
-    if (offset_offset > 0) {
-      string->int_field_put(offset_offset, offset);
-    }
-  }
-  static void set_count( oop string, int count) {
-    assert(initialized, "Must be initialized");
-    if (count_offset > 0) {
-      string->int_field_put(count_offset,  count);
+    if (coder_offset > 0) {
+      string->byte_field_put(coder_offset, coder);
     }
   }
 
  public:
+
+  // Coders
+  enum Coder {
+    CODER_LATIN1 =  0,
+    CODER_UTF16  =  1
+  };
+
   static void compute_offsets();
 
   // Instance creation
@@ -86,37 +86,29 @@
   static Handle create_from_platform_dependent_str(const char* str, TRAPS);
   static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
 
-  static bool has_offset_field()  {
-    assert(initialized, "Must be initialized");
-    return (offset_offset > 0);
-  }
-
-  static bool has_count_field()  {
-    assert(initialized, "Must be initialized");
-    return (count_offset > 0);
-  }
-
   static bool has_hash_field()  {
     assert(initialized, "Must be initialized");
     return (hash_offset > 0);
   }
+  static bool has_coder_field()  {
+    assert(initialized, "Must be initialized");
+    return (coder_offset > 0);
+  }
+
+  static void set_compact_strings(bool value);
 
   static int value_offset_in_bytes()  {
     assert(initialized && (value_offset > 0), "Must be initialized");
     return value_offset;
   }
-  static int count_offset_in_bytes()  {
-    assert(initialized && (count_offset > 0), "Must be initialized");
-    return count_offset;
-  }
-  static int offset_offset_in_bytes() {
-    assert(initialized && (offset_offset > 0), "Must be initialized");
-    return offset_offset;
-  }
   static int hash_offset_in_bytes()   {
     assert(initialized && (hash_offset > 0), "Must be initialized");
     return hash_offset;
   }
+  static int coder_offset_in_bytes()   {
+    assert(initialized && (coder_offset > 0), "Must be initialized");
+    return coder_offset;
+  }
 
   static void set_value_raw(oop string, typeArrayOop buffer) {
     assert(initialized, "Must be initialized");
@@ -142,28 +134,30 @@
     assert(is_instance(java_string), "must be java_string");
     return java_string->int_field(hash_offset);
   }
-  static int offset(oop java_string) {
+  static bool is_latin1(oop java_string) {
     assert(initialized, "Must be initialized");
     assert(is_instance(java_string), "must be java_string");
-    if (offset_offset > 0) {
-      return java_string->int_field(offset_offset);
+    if (coder_offset > 0) {
+      jbyte coder = java_string->byte_field(coder_offset);
+      assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
+      return coder == CODER_LATIN1;
     } else {
-      return 0;
+      return false;
     }
   }
   static int length(oop java_string) {
     assert(initialized, "Must be initialized");
     assert(is_instance(java_string), "must be java_string");
-    if (count_offset > 0) {
-      return java_string->int_field(count_offset);
-    } else {
-      typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset));
-      if (value_array == NULL) {
-        return 0;
-      } else {
-        return value_array->length();
-      }
+    typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset));
+    if (value_array == NULL) {
+     return 0;
     }
+    int arr_length = value_array->length();
+    if (!is_latin1(java_string)) {
+      assert((arr_length & 1) == 0, "should be even for UTF16 string");
+      arr_length >>= 1; // convert number of bytes to number of elements
+    }
+    return arr_length;
   }
   static int utf8_length(oop java_string);
 
@@ -187,7 +181,7 @@
   // hash P(31) from Kernighan & Ritchie
   //
   // For this reason, THIS ALGORITHM MUST MATCH String.hashCode().
-  template <typename T> static unsigned int hash_code(T* s, int len) {
+  static unsigned int hash_code(const jchar* s, int len) {
     unsigned int h = 0;
     while (len-- > 0) {
       h = 31*h + (unsigned int) *s;
@@ -195,7 +189,18 @@
     }
     return h;
   }
+
+  static unsigned int hash_code(const jbyte* s, int len) {
+    unsigned int h = 0;
+    while (len-- > 0) {
+      h = 31*h + (((unsigned int) *s) & 0xFF);
+      s++;
+    }
+    return h;
+  }
+
   static unsigned int hash_code(oop java_string);
+  static unsigned int latin1_hash_code(typeArrayOop value, int len);
 
   // This is the string hash code used by the StringTable, which may be
   // the same as String.hashCode or an alternate hash code.
@@ -451,7 +456,7 @@
   // parent ThreadGroup
   static oop  parent(oop java_thread_group);
   // name
-  static typeArrayOop name(oop java_thread_group);
+  static const char* name(oop java_thread_group);
   // ("name as oop" accessor is not necessary)
   // Number of threads in group
   static int nthreads(oop java_thread_group);
@@ -532,7 +537,7 @@
   static Symbol* detail_message(oop throwable);
   static void print_stack_element(outputStream *st, Handle mirror, int method,
                                   int version, int bci, int cpref);
-  static void print_stack_element(outputStream *st, methodHandle method, int bci);
+  static void print_stack_element(outputStream *st, const methodHandle& method, int bci);
   static void print_stack_usage(Handle stream);
 
   // Allocate space for backtrace (created but stack trace not filled in)
@@ -540,8 +545,8 @@
   // Fill in current stack trace for throwable with preallocated backtrace (no GC)
   static void fill_in_stack_trace_of_preallocated_backtrace(Handle throwable);
   // Fill in current stack trace, can cause GC
-  static void fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS);
-  static void fill_in_stack_trace(Handle throwable, methodHandle method = methodHandle());
+  static void fill_in_stack_trace(Handle throwable, const methodHandle& method, TRAPS);
+  static void fill_in_stack_trace(Handle throwable, const methodHandle& method = methodHandle());
   // Programmatic access to stack trace
   static oop  get_stack_trace_element(oop throwable, int index, TRAPS);
   static int  get_stack_trace_depth(oop throwable, TRAPS);
@@ -1347,7 +1352,7 @@
 
   // Create an instance of StackTraceElement
   static oop create(Handle mirror, int method, int version, int bci, int cpref, TRAPS);
-  static oop create(methodHandle method, int bci, TRAPS);
+  static oop create(const methodHandle& method, int bci, TRAPS);
 
   // Debugging
   friend class JavaClasses;
--- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -320,7 +320,7 @@
                                                        Handle loader) {
   LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
   if (p != NULL && p->klass() != NULL) {
-    if (p->klass()->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) {
+    if (p->klass()->is_instance_klass() && !InstanceKlass::cast(p->klass())->is_loaded()) {
       // Only return fully loaded classes.  Classes found through the
       // constraints might still be in the process of loading.
       return NULL;
--- a/hotspot/src/share/vm/classfile/placeholders.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/placeholders.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -244,7 +244,7 @@
   guarantee(loader_data()->class_loader() == NULL || loader_data()->class_loader()->is_instance(),
             "checking type of _loader");
   guarantee(instance_klass() == NULL
-            || instance_klass()->oop_is_instance(),
+            || instance_klass()->is_instance_klass(),
             "checking type of instance_klass result");
 }
 
--- a/hotspot/src/share/vm/classfile/placeholders.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/placeholders.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -220,7 +220,7 @@
   }
 
   SeenThread* actionToQueue(PlaceholderTable::classloadAction action) {
-    SeenThread* queuehead;
+    SeenThread* queuehead = NULL;
     switch (action) {
       case PlaceholderTable::LOAD_INSTANCE:
          queuehead = _loadInstanceThreadQ;
--- a/hotspot/src/share/vm/classfile/resolutionErrors.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/resolutionErrors.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
 
 // add new entry to the table
 void ResolutionErrorTable::add_entry(int index, unsigned int hash,
-                                     constantPoolHandle pool, int cp_index,
+                                     const constantPoolHandle& pool, int cp_index,
                                      Symbol* error, Symbol* message)
 {
   assert_locked_or_safepoint(SystemDictionary_lock);
@@ -44,7 +44,7 @@
 
 // find entry in the table
 ResolutionErrorEntry* ResolutionErrorTable::find_entry(int index, unsigned int hash,
-                                                       constantPoolHandle pool, int cp_index)
+                                                       const constantPoolHandle& pool, int cp_index)
 {
   assert_locked_or_safepoint(SystemDictionary_lock);
 
--- a/hotspot/src/share/vm/classfile/resolutionErrors.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/resolutionErrors.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,15 +56,15 @@
   }
 
   void add_entry(int index, unsigned int hash,
-                 constantPoolHandle pool, int which, Symbol* error, Symbol* message);
+                 const constantPoolHandle& pool, int which, Symbol* error, Symbol* message);
 
 
   // find error given the constant pool and constant pool index
   ResolutionErrorEntry* find_entry(int index, unsigned int hash,
-                                   constantPoolHandle pool, int cp_index);
+                                   const constantPoolHandle& pool, int cp_index);
 
 
-  unsigned int compute_hash(constantPoolHandle pool, int cp_index) {
+  unsigned int compute_hash(const constantPoolHandle& pool, int cp_index) {
     return (unsigned int) pool->identity_hash() + cp_index;
   }
 
--- a/hotspot/src/share/vm/classfile/stringTable.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -94,11 +94,16 @@
 CompactHashtable<oop, char> StringTable::_shared_table;
 
 // Pick hashing algorithm
-unsigned int StringTable::hash_string(const jchar* s, int len) {
+template<typename T>
+unsigned int StringTable::hash_string(const T* s, int len) {
   return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
                                     java_lang_String::hash_code(s, len);
 }
 
+// Explicit instantiation for all supported types.
+template unsigned int StringTable::hash_string<jchar>(const jchar* s, int len);
+template unsigned int StringTable::hash_string<jbyte>(const jbyte* s, int len);
+
 oop StringTable::lookup_shared(jchar* name, int len) {
   // java_lang_String::hash_code() was used to compute hash values in the shared table. Don't
   // use the hash value from StringTable::hash_string() as it might use alternate hashcode.
@@ -409,17 +414,25 @@
       for ( ; p != NULL; p = p->next()) {
         oop s = p->literal();
         typeArrayOop value  = java_lang_String::value(s);
-        int          offset = java_lang_String::offset(s);
         int          length = java_lang_String::length(s);
+        bool      is_latin1 = java_lang_String::is_latin1(s);
 
         if (length <= 0) {
           st->print("%d: ", length);
         } else {
           ResourceMark rm(THREAD);
-          jchar* chars = (jchar*)value->char_at_addr(offset);
-          int utf8_length = UNICODE::utf8_length(chars, length);
-          char* utf8_string = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
-          UNICODE::convert_to_utf8(chars, length, utf8_string);
+          int utf8_length;
+          char* utf8_string;
+
+          if (!is_latin1) {
+            jchar* chars = value->char_at_addr(0);
+            utf8_length = UNICODE::utf8_length(chars, length);
+            utf8_string = UNICODE::as_utf8(chars, length);
+          } else {
+            jbyte* bytes = value->byte_at_addr(0);
+            utf8_length = UNICODE::utf8_length(bytes, length);
+            utf8_string = UNICODE::as_utf8(bytes, length);
+          }
 
           st->print("%d: ", utf8_length);
           HashtableTextDump::put_utf8(st, utf8_string, utf8_length);
--- a/hotspot/src/share/vm/classfile/stringTable.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -111,7 +111,7 @@
   // Hashing algorithm, used as the hash value used by the
   //     StringTable for bucket selection and comparison (stored in the
   //     HashtableEntry structures).  This is used in the String.intern() method.
-  static unsigned int hash_string(const jchar* s, int len);
+  template<typename T> static unsigned int hash_string(const T* s, int len);
 
   // Internal test.
   static void test_alt_hash() PRODUCT_RETURN;
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -244,7 +244,7 @@
 unsigned int SymbolTable::hash_symbol(const char* s, int len) {
   return use_alternate_hashcode() ?
            AltHashing::murmur3_32(seed(), (const jbyte*)s, len) :
-           java_lang_String::hash_code(s, len);
+           java_lang_String::hash_code((const jbyte*)s, len);
 }
 
 
@@ -371,7 +371,7 @@
   }
 }
 
-void SymbolTable::add(ClassLoaderData* loader_data, constantPoolHandle cp,
+void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp,
                       int names_count,
                       const char** names, int* lengths, int* cp_indices,
                       unsigned int* hashValues, TRAPS) {
@@ -452,7 +452,7 @@
 
 // This version of basic_add adds symbols in batch from the constant pool
 // parsing.
-bool SymbolTable::basic_add(ClassLoaderData* loader_data, constantPoolHandle cp,
+bool SymbolTable::basic_add(ClassLoaderData* loader_data, const constantPoolHandle& cp,
                             int names_count,
                             const char** names, int* lengths,
                             int* cp_indices, unsigned int* hashValues,
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -100,12 +100,12 @@
   Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,
                     bool c_heap, TRAPS);
   bool basic_add(ClassLoaderData* loader_data,
-                 constantPoolHandle cp, int names_count,
+                 const constantPoolHandle& cp, int names_count,
                  const char** names, int* lengths, int* cp_indices,
                  unsigned int* hashValues, TRAPS);
 
   static void new_symbols(ClassLoaderData* loader_data,
-                          constantPoolHandle cp, int names_count,
+                          const constantPoolHandle& cp, int names_count,
                           const char** name, int* lengths,
                           int* cp_indices, unsigned int* hashValues,
                           TRAPS) {
@@ -165,12 +165,12 @@
   // Look up the address of the literal in the SymbolTable for this Symbol*
   static Symbol** lookup_symbol_addr(Symbol* sym);
 
-  // jchar (utf16) version of lookups
+  // jchar (UTF16) version of lookups
   static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
   static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
 
   static void add(ClassLoaderData* loader_data,
-                  constantPoolHandle cp, int names_count,
+                  const constantPoolHandle& cp, int names_count,
                   const char** names, int* lengths, int* cp_indices,
                   unsigned int* hashValues, TRAPS);
 
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -88,10 +88,10 @@
 
 oop         SystemDictionary::_system_loader_lock_obj     =  NULL;
 
-Klass*      SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT]
+InstanceKlass*      SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT]
                                                           =  { NULL /*, NULL...*/ };
 
-Klass*      SystemDictionary::_box_klasses[T_VOID+1]      =  { NULL /*, NULL...*/ };
+InstanceKlass*      SystemDictionary::_box_klasses[T_VOID+1]      =  { NULL /*, NULL...*/ };
 
 oop         SystemDictionary::_java_system_loader         =  NULL;
 
@@ -99,7 +99,7 @@
 bool        SystemDictionary::_has_checkPackageAccess     =  false;
 
 // lazily initialized klass variables
-Klass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL;
+InstanceKlass* volatile SystemDictionary::_abstract_ownable_synchronizer_klass = NULL;
 
 
 // ----------------------------------------------------------------------------
@@ -357,7 +357,7 @@
     // so we don't throw an exception here.
     // see: nsk redefclass014 & java.lang.instrument Instrument032
     if ((childk != NULL ) && (is_superclass) &&
-       ((quicksuperk = InstanceKlass::cast(childk)->super()) != NULL) &&
+       ((quicksuperk = childk->super()) != NULL) &&
 
          ((quicksuperk->name() == class_name) &&
             (quicksuperk->class_loader()  == class_loader()))) {
@@ -1257,8 +1257,7 @@
     }
 
     // notify a class loaded from shared object
-    ClassLoadingService::notify_class_loaded(InstanceKlass::cast(ik()),
-                                             true /* shared class */);
+    ClassLoadingService::notify_class_loaded(ik(), true /* shared class */);
   }
   return ik;
 }
@@ -1805,7 +1804,7 @@
     Klass* k = resolve_or_fail(vmSymbols::java_util_concurrent_locks_AbstractOwnableSynchronizer(), true, CHECK);
     // Force a fence to prevent any read before the write completes
     OrderAccess::fence();
-    _abstract_ownable_synchronizer_klass = k;
+    _abstract_ownable_synchronizer_klass = InstanceKlass::cast(k);
   }
 }
 
@@ -1846,14 +1845,16 @@
   int  info = wk_init_info[id - FIRST_WKID];
   int  sid  = (info >> CEIL_LG_OPTION_LIMIT);
   Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
-  Klass**    klassp = &_well_known_klasses[id];
+  InstanceKlass** klassp = &_well_known_klasses[id];
   bool must_load = (init_opt < SystemDictionary::Opt);
   if ((*klassp) == NULL) {
+    Klass* k;
     if (must_load) {
-      (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class
+      k = resolve_or_fail(symbol, true, CHECK_0); // load required class
     } else {
-      (*klassp) = resolve_or_null(symbol,       CHECK_0); // load optional klass
+      k = resolve_or_null(symbol,       CHECK_0); // load optional klass
     }
+    (*klassp) = (k == NULL) ? NULL : InstanceKlass::cast(k);
   }
   return ((*klassp) != NULL);
 }
@@ -1966,7 +1967,8 @@
                                          instanceKlassHandle k,
                                          Handle class_loader, bool defining,
                                          TRAPS) {
-  const char *linkage_error = NULL;
+  const char *linkage_error1 = NULL;
+  const char *linkage_error2 = NULL;
   {
     Symbol*  name  = k->name();
     ClassLoaderData *loader_data = class_loader_data(class_loader);
@@ -1981,10 +1983,10 @@
       // system dictionary only holds instance classes, placeholders
       // also holds array classes
 
-      assert(check->oop_is_instance(), "noninstance in systemdictionary");
+      assert(check->is_instance_klass(), "noninstance in systemdictionary");
       if ((defining == true) || (k() != check)) {
-        linkage_error = "loader (instance of  %s): attempted  duplicate class "
-          "definition for name: \"%s\"";
+        linkage_error1 = "loader (instance of  ";
+        linkage_error2 = "): attempted  duplicate class definition for name: \"";
       } else {
         return;
       }
@@ -1995,10 +1997,10 @@
     assert(ph_check == NULL || ph_check == name, "invalid symbol");
 #endif
 
-    if (linkage_error == NULL) {
+    if (linkage_error1 == NULL) {
       if (constraints()->check_or_update(k, class_loader, name) == false) {
-        linkage_error = "loader constraint violation: loader (instance of %s)"
-          " previously initiated loading for a different type with name \"%s\"";
+        linkage_error1 = "loader constraint violation: loader (instance of ";
+        linkage_error2 = ") previously initiated loading for a different type with name \"";
       }
     }
   }
@@ -2006,14 +2008,14 @@
   // Throw error now if needed (cannot throw while holding
   // SystemDictionary_lock because of rank ordering)
 
-  if (linkage_error) {
+  if (linkage_error1) {
     ResourceMark rm(THREAD);
     const char* class_loader_name = loader_name(class_loader());
     char* type_name = k->name()->as_C_string();
-    size_t buflen = strlen(linkage_error) + strlen(class_loader_name) +
-      strlen(type_name);
+    size_t buflen = strlen(linkage_error1) + strlen(class_loader_name) +
+      strlen(linkage_error2) + strlen(type_name) + 2; // +2 for '"' and null byte.
     char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
-    jio_snprintf(buf, buflen, linkage_error, class_loader_name, type_name);
+    jio_snprintf(buf, buflen, "%s%s%s%s\"", linkage_error1, class_loader_name, linkage_error2, type_name);
     THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
   }
 }
@@ -2155,7 +2157,7 @@
 
 // Add entry to resolution error table to record the error when the first
 // attempt to resolve a reference to a class has failed.
-void SystemDictionary::add_resolution_error(constantPoolHandle pool, int which,
+void SystemDictionary::add_resolution_error(const constantPoolHandle& pool, int which,
                                             Symbol* error, Symbol* message) {
   unsigned int hash = resolution_errors()->compute_hash(pool, which);
   int index = resolution_errors()->hash_to_index(hash);
@@ -2171,7 +2173,7 @@
 }
 
 // Lookup resolution error table. Returns error if found, otherwise NULL.
-Symbol* SystemDictionary::find_resolution_error(constantPoolHandle pool, int which,
+Symbol* SystemDictionary::find_resolution_error(const constantPoolHandle& pool, int which,
                                                 Symbol** message) {
   unsigned int hash = resolution_errors()->compute_hash(pool, which);
   int index = resolution_errors()->hash_to_index(hash);
@@ -2387,13 +2389,13 @@
 // Out of an abundance of caution, we do not include any other classes, not even for packages like java.util.
 static bool is_always_visible_class(oop mirror) {
   Klass* klass = java_lang_Class::as_Klass(mirror);
-  if (klass->oop_is_objArray()) {
+  if (klass->is_objArray_klass()) {
     klass = ObjArrayKlass::cast(klass)->bottom_klass(); // check element type
   }
-  if (klass->oop_is_typeArray()) {
+  if (klass->is_typeArray_klass()) {
     return true; // primitive array
   }
-  assert(klass->oop_is_instance(), "%s", klass->external_name());
+  assert(klass->is_instance_klass(), "%s", klass->external_name());
   return klass->is_public() &&
          (InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::Object_klass()) ||       // java.lang
           InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::MethodHandle_klass()));  // java.lang.invoke
@@ -2457,9 +2459,9 @@
       Klass* sel_klass = java_lang_Class::as_Klass(mirror);
       mirror = NULL;  // safety
       // Emulate ConstantPool::verify_constant_pool_resolve.
-      if (sel_klass->oop_is_objArray())
+      if (sel_klass->is_objArray_klass())
         sel_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass();
-      if (sel_klass->oop_is_instance()) {
+      if (sel_klass->is_instance_klass()) {
         KlassHandle sel_kh(THREAD, sel_klass);
         LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty));
       }
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -168,7 +168,7 @@
                                                                                                                          \
   do_klass(StringBuffer_klass,                          java_lang_StringBuffer,                    Pre                 ) \
   do_klass(StringBuilder_klass,                         java_lang_StringBuilder,                   Pre                 ) \
-  do_klass(misc_Unsafe_klass,                           sun_misc_Unsafe,                           Pre                 ) \
+  do_klass(internal_Unsafe_klass,                       jdk_internal_misc_Unsafe,                  Pre                 ) \
                                                                                                                          \
   /* support for CDS */                                                                                                  \
   do_klass(ByteArrayInputStream_klass,                  java_io_ByteArrayInputStream,              Pre                 ) \
@@ -403,15 +403,15 @@
   static void initialize(TRAPS);
 
   // Fast access to commonly used classes (preloaded)
-  static Klass* check_klass(Klass* k) {
+  static InstanceKlass* check_klass(InstanceKlass* k) {
     assert(k != NULL, "preloaded klass not initialized");
     return k;
   }
 
-  static Klass* check_klass_Pre(       Klass* k) { return check_klass(k); }
-  static Klass* check_klass_Opt(       Klass* k) { return k; }
+  static InstanceKlass* check_klass_Pre(InstanceKlass* k) { return check_klass(k); }
+  static InstanceKlass* check_klass_Opt(InstanceKlass* k) { return k; }
 
-  JVMCI_ONLY(static Klass* check_klass_Jvmci(Klass* k) { return k; })
+  JVMCI_ONLY(static InstanceKlass* check_klass_Jvmci(InstanceKlass* k) { return k; })
 
   static bool initialize_wk_klass(WKID id, int init_opt, TRAPS);
   static void initialize_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS);
@@ -422,19 +422,19 @@
 
 public:
   #define WK_KLASS_DECLARE(name, symbol, option) \
-    static Klass* name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
-    static Klass** name##_addr() {                                                                       \
+    static InstanceKlass* name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } \
+    static InstanceKlass** name##_addr() {                                                                       \
       return &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)];           \
     }
   WK_KLASSES_DO(WK_KLASS_DECLARE);
   #undef WK_KLASS_DECLARE
 
-  static Klass* well_known_klass(WKID id) {
+  static InstanceKlass* well_known_klass(WKID id) {
     assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
     return _well_known_klasses[id];
   }
 
-  static Klass** well_known_klass_addr(WKID id) {
+  static InstanceKlass** well_known_klass_addr(WKID id) {
     assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
     return &_well_known_klasses[id];
   }
@@ -442,7 +442,7 @@
   // Local definition for direct access to the private array:
   #define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]
 
-  static Klass* box_klass(BasicType t) {
+  static InstanceKlass* box_klass(BasicType t) {
     assert((uint)t < T_VOID+1, "range check");
     return check_klass(_box_klasses[t]);
   }
@@ -450,7 +450,7 @@
 
   // methods returning lazily loaded klasses
   // The corresponding method to load the class must be called before calling them.
-  static Klass* abstract_ownable_synchronizer_klass() { return check_klass(_abstract_ownable_synchronizer_klass); }
+  static InstanceKlass* abstract_ownable_synchronizer_klass() { return check_klass(_abstract_ownable_synchronizer_klass); }
 
   static void load_abstract_ownable_synchronizer_klass(TRAPS);
 
@@ -547,10 +547,10 @@
 
   // Record the error when the first attempt to resolve a reference from a constant
   // pool entry to a class fails.
-  static void add_resolution_error(constantPoolHandle pool, int which, Symbol* error,
+  static void add_resolution_error(const constantPoolHandle& pool, int which, Symbol* error,
                                    Symbol* message);
   static void delete_resolution_error(ConstantPool* pool);
-  static Symbol* find_resolution_error(constantPoolHandle pool, int which,
+  static Symbol* find_resolution_error(const constantPoolHandle& pool, int which,
                                        Symbol** message);
 
  protected:
@@ -700,13 +700,13 @@
                                 TRAPS);
 
   // Variables holding commonly used klasses (preloaded)
-  static Klass* _well_known_klasses[];
+  static InstanceKlass* _well_known_klasses[];
 
   // Lazily loaded klasses
-  static Klass* volatile _abstract_ownable_synchronizer_klass;
+  static InstanceKlass* volatile _abstract_ownable_synchronizer_klass;
 
   // table of box klasses (int_klass, etc.)
-  static Klass* _box_klasses[T_VOID+1];
+  static InstanceKlass* _box_klasses[T_VOID+1];
 
   static oop  _java_system_loader;
 
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -184,7 +184,7 @@
     if (HAS_PENDING_EXCEPTION) {
       tty->print("Verification for %s has", klassName);
       tty->print_cr(" exception pending %s ",
-        InstanceKlass::cast(PENDING_EXCEPTION->klass())->external_name());
+        PENDING_EXCEPTION->klass()->external_name());
     } else if (exception_name != NULL) {
       tty->print_cr("Verification for %s failed", klassName);
     }
@@ -605,7 +605,7 @@
   }
 }
 
-void ClassVerifier::verify_method(methodHandle m, TRAPS) {
+void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
   HandleMark hm(THREAD);
   _method = m;   // initialize _method
   if (VerboseVerification) {
@@ -1901,7 +1901,7 @@
 }
 
 void ClassVerifier::verify_cp_index(
-    u2 bci, constantPoolHandle cp, int index, TRAPS) {
+    u2 bci, const constantPoolHandle& cp, int index, TRAPS) {
   int nconstants = cp->length();
   if ((index <= 0) || (index >= nconstants)) {
     verify_error(ErrorContext::bad_cp_index(bci, index),
@@ -1912,7 +1912,7 @@
 }
 
 void ClassVerifier::verify_cp_type(
-    u2 bci, int index, constantPoolHandle cp, unsigned int types, TRAPS) {
+    u2 bci, int index, const constantPoolHandle& cp, unsigned int types, TRAPS) {
 
   // In some situations, bytecode rewriting may occur while we're verifying.
   // In this case, a constant pool cache exists and some indices refer to that
@@ -1931,7 +1931,7 @@
 }
 
 void ClassVerifier::verify_cp_class_type(
-    u2 bci, int index, constantPoolHandle cp, TRAPS) {
+    u2 bci, int index, const constantPoolHandle& cp, TRAPS) {
   verify_cp_index(bci, cp, index, CHECK_VERIFY(this));
   constantTag tag = cp->tag_at(index);
   if (!tag.is_klass() && !tag.is_unresolved_klass()) {
@@ -2023,7 +2023,7 @@
 
 void ClassVerifier::verify_ldc(
     int opcode, u2 index, StackMapFrame* current_frame,
-    constantPoolHandle cp, u2 bci, TRAPS) {
+    const constantPoolHandle& cp, u2 bci, TRAPS) {
   verify_cp_index(bci, cp, index, CHECK_VERIFY(this));
   constantTag tag = cp->tag_at(index);
   unsigned int types;
@@ -2165,7 +2165,7 @@
 
 void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs,
                                               StackMapFrame* current_frame,
-                                              constantPoolHandle cp,
+                                              const constantPoolHandle& cp,
                                               bool allow_arrays,
                                               TRAPS) {
   u2 index = bcs->get_index_u2();
@@ -2477,7 +2477,7 @@
 void ClassVerifier::verify_invoke_init(
     RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
     StackMapFrame* current_frame, u4 code_length, bool in_try_block,
-    bool *this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
+    bool *this_uninit, const constantPoolHandle& cp, StackMapTable* stackmap_table,
     TRAPS) {
   u2 bci = bcs->bci();
   VerificationType type = current_frame->pop_stack(
@@ -2613,7 +2613,7 @@
 void ClassVerifier::verify_invoke_instructions(
     RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
     bool in_try_block, bool *this_uninit, VerificationType return_type,
-    constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS) {
+    const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS) {
   // Make sure the constant pool item is the right type
   u2 index = bcs->get_index_u2();
   Bytecodes::Code opcode = bcs->raw_code();
@@ -2878,7 +2878,7 @@
 }
 
 void ClassVerifier::verify_anewarray(
-    u2 bci, u2 index, constantPoolHandle cp,
+    u2 bci, u2 index, const constantPoolHandle& cp,
     StackMapFrame* current_frame, TRAPS) {
   verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));
   current_frame->pop_stack(
--- a/hotspot/src/share/vm/classfile/verifier.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/verifier.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -262,14 +262,14 @@
 
   ErrorContext _error_context;  // contains information about an error
 
-  void verify_method(methodHandle method, TRAPS);
+  void verify_method(const methodHandle& method, TRAPS);
   char* generate_code_data(methodHandle m, u4 code_length, TRAPS);
   void verify_exception_handler_table(u4 code_length, char* code_data,
                                       int& min, int& max, TRAPS);
   void verify_local_variable_table(u4 code_length, char* code_data, TRAPS);
 
   VerificationType cp_ref_index_to_type(
-      int index, constantPoolHandle cp, TRAPS) {
+      int index, const constantPoolHandle& cp, TRAPS) {
     return cp_index_to_type(cp->klass_ref_index_at(index), cp, THREAD);
   }
 
@@ -277,10 +277,10 @@
     instanceKlassHandle this_class, Klass* target_class,
     Symbol* field_name, Symbol* field_sig, bool is_method);
 
-  void verify_cp_index(u2 bci, constantPoolHandle cp, int index, TRAPS);
-  void verify_cp_type(u2 bci, int index, constantPoolHandle cp,
+  void verify_cp_index(u2 bci, const constantPoolHandle& cp, int index, TRAPS);
+  void verify_cp_type(u2 bci, int index, const constantPoolHandle& cp,
       unsigned int types, TRAPS);
-  void verify_cp_class_type(u2 bci, int index, constantPoolHandle cp, TRAPS);
+  void verify_cp_class_type(u2 bci, int index, const constantPoolHandle& cp, TRAPS);
 
   u2 verify_stackmap_table(
     u2 stackmap_index, u2 bci, StackMapFrame* current_frame,
@@ -292,7 +292,7 @@
 
   void verify_ldc(
     int opcode, u2 index, StackMapFrame *current_frame,
-    constantPoolHandle cp, u2 bci, TRAPS);
+    const constantPoolHandle& cp, u2 bci, TRAPS);
 
   void verify_switch(
     RawBytecodeStream* bcs, u4 code_length, char* code_data,
@@ -300,12 +300,12 @@
 
   void verify_field_instructions(
     RawBytecodeStream* bcs, StackMapFrame* current_frame,
-    constantPoolHandle cp, bool allow_arrays, TRAPS);
+    const constantPoolHandle& cp, bool allow_arrays, TRAPS);
 
   void verify_invoke_init(
     RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
     StackMapFrame* current_frame, u4 code_length, bool in_try_block,
-    bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,
+    bool* this_uninit, const constantPoolHandle& cp, StackMapTable* stackmap_table,
     TRAPS);
 
   // Used by ends_in_athrow() to push all handlers that contain bci onto the
@@ -322,10 +322,10 @@
   void verify_invoke_instructions(
     RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
     bool in_try_block, bool* this_uninit, VerificationType return_type,
-    constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);
+    const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS);
 
   VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);
-  void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,
+  void verify_anewarray(u2 bci, u2 index, const constantPoolHandle& cp,
       StackMapFrame* current_frame, TRAPS);
   void verify_return_value(
       VerificationType return_type, VerificationType type, u2 offset,
@@ -406,7 +406,7 @@
   int change_sig_to_verificationType(
     SignatureStream* sig_type, VerificationType* inference_type, TRAPS);
 
-  VerificationType cp_index_to_type(int index, constantPoolHandle cp, TRAPS) {
+  VerificationType cp_index_to_type(int index, const constantPoolHandle& cp, TRAPS) {
     return VerificationType::reference_type(cp->klass_name_at(index));
   }
 
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -417,7 +417,7 @@
   }
 }
 
-bool vmIntrinsics::is_disabled_by_flags(methodHandle method) {
+bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
   vmIntrinsics::ID id = method->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
 
@@ -425,10 +425,26 @@
   // the following switch statement.
   if (!InlineNatives) {
     switch (id) {
-    case vmIntrinsics::_indexOf:
-    case vmIntrinsics::_compareTo:
-    case vmIntrinsics::_equals:
+    case vmIntrinsics::_indexOfL:
+    case vmIntrinsics::_indexOfU:
+    case vmIntrinsics::_indexOfUL:
+    case vmIntrinsics::_indexOfIL:
+    case vmIntrinsics::_indexOfIU:
+    case vmIntrinsics::_indexOfIUL:
+    case vmIntrinsics::_indexOfU_char:
+    case vmIntrinsics::_compareToL:
+    case vmIntrinsics::_compareToU:
+    case vmIntrinsics::_compareToLU:
+    case vmIntrinsics::_compareToUL:
+    case vmIntrinsics::_equalsL:
+    case vmIntrinsics::_equalsU:
     case vmIntrinsics::_equalsC:
+    case vmIntrinsics::_getCharStringU:
+    case vmIntrinsics::_putCharStringU:
+    case vmIntrinsics::_compressStringC:
+    case vmIntrinsics::_compressStringB:
+    case vmIntrinsics::_inflateStringC:
+    case vmIntrinsics::_inflateStringB:
     case vmIntrinsics::_getAndAddInt:
     case vmIntrinsics::_getAndAddLong:
     case vmIntrinsics::_getAndSetInt:
@@ -437,6 +453,7 @@
     case vmIntrinsics::_loadFence:
     case vmIntrinsics::_storeFence:
     case vmIntrinsics::_fullFence:
+    case vmIntrinsics::_hasNegatives:
     case vmIntrinsics::_Reference_get:
       break;
     default:
@@ -619,19 +636,31 @@
     // intrinsic mechanism.
     if (!InlineObjectCopy || !InlineArrayCopy) return true;
     break;
-  case vmIntrinsics::_compareTo:
+  case vmIntrinsics::_compareToL:
+  case vmIntrinsics::_compareToU:
+  case vmIntrinsics::_compareToLU:
+  case vmIntrinsics::_compareToUL:
     if (!SpecialStringCompareTo) return true;
     break;
-  case vmIntrinsics::_indexOf:
+  case vmIntrinsics::_indexOfL:
+  case vmIntrinsics::_indexOfU:
+  case vmIntrinsics::_indexOfUL:
+  case vmIntrinsics::_indexOfIL:
+  case vmIntrinsics::_indexOfIU:
+  case vmIntrinsics::_indexOfIUL:
+  case vmIntrinsics::_indexOfU_char:
     if (!SpecialStringIndexOf) return true;
     break;
-  case vmIntrinsics::_equals:
+  case vmIntrinsics::_equalsL:
+  case vmIntrinsics::_equalsU:
     if (!SpecialStringEquals) return true;
     break;
+  case vmIntrinsics::_equalsB:
   case vmIntrinsics::_equalsC:
     if (!SpecialArraysEquals) return true;
     break;
   case vmIntrinsics::_encodeISOArray:
+  case vmIntrinsics::_encodeByteISOArray:
     if (!SpecialEncodeISOArray) return true;
     break;
   case vmIntrinsics::_getCallerClass:
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -53,6 +53,8 @@
   template(java_lang_Object,                          "java/lang/Object")                         \
   template(java_lang_Class,                           "java/lang/Class")                          \
   template(java_lang_String,                          "java/lang/String")                         \
+  template(java_lang_StringLatin1,                    "java/lang/StringLatin1")                   \
+  template(java_lang_StringUTF16,                     "java/lang/StringUTF16")                    \
   template(java_lang_Thread,                          "java/lang/Thread")                         \
   template(java_lang_ThreadGroup,                     "java/lang/ThreadGroup")                    \
   template(java_lang_Cloneable,                       "java/lang/Cloneable")                      \
@@ -381,9 +383,9 @@
   template(park_event_name,                           "nativeParkEventPointer")                   \
   template(cache_field_name,                          "cache")                                    \
   template(value_name,                                "value")                                    \
-  template(offset_name,                               "offset")                                   \
-  template(count_name,                                "count")                                    \
   template(hash_name,                                 "hash")                                     \
+  template(coder_name,                                "coder")                                    \
+  template(compact_strings_name,                      "COMPACT_STRINGS")                          \
   template(numberOfLeadingZeros_name,                 "numberOfLeadingZeros")                     \
   template(numberOfTrailingZeros_name,                "numberOfTrailingZeros")                    \
   template(bitCount_name,                             "bitCount")                                 \
@@ -837,22 +839,66 @@
                                                                                                                         \
   do_intrinsic(_equalsC,                  java_util_Arrays,       equals_name,    equalsC_signature,             F_S)   \
    do_signature(equalsC_signature,                               "([C[C)Z")                                             \
+  do_intrinsic(_equalsB,                  java_util_Arrays,       equals_name,    equalsB_signature,             F_S)   \
+   do_signature(equalsB_signature,                               "([B[B)Z")                                             \
                                                                                                                         \
-  do_intrinsic(_compareTo,                java_lang_String,       compareTo_name, string_int_signature,          F_R)   \
+  do_intrinsic(_compressStringC,          java_lang_StringUTF16,  compress_name, encodeISOArray_signature,       F_S)   \
+   do_name(     compress_name,                                   "compress")                                            \
+  do_intrinsic(_compressStringB,          java_lang_StringUTF16,  compress_name, indexOfI_signature,             F_S)   \
+  do_intrinsic(_inflateStringC,           java_lang_StringLatin1, inflate_name, inflateC_signature,              F_S)   \
+   do_name(     inflate_name,                                    "inflate")                                             \
+   do_signature(inflateC_signature,                              "([BI[CII)V")                                          \
+  do_intrinsic(_inflateStringB,           java_lang_StringLatin1, inflate_name, inflateB_signature,              F_S)   \
+   do_signature(inflateB_signature,                              "([BI[BII)V")                                          \
+  do_intrinsic(_toBytesStringU,           java_lang_StringUTF16, toBytes_name, toBytesU_signature,               F_S)   \
+   do_name(     toBytes_name,                                    "toBytes")                                             \
+   do_signature(toBytesU_signature,                              "([CII)[B")                                            \
+  do_intrinsic(_getCharsStringU,          java_lang_StringUTF16, getCharsU_name, getCharsU_signature,            F_S)   \
+   do_name(     getCharsU_name,                                  "getChars")                                            \
+   do_signature(getCharsU_signature,                             "([BII[CI)V")                                          \
+  do_intrinsic(_getCharStringU,           java_lang_StringUTF16, getChar_name, getCharStringU_signature,         F_S)   \
+   do_signature(getCharStringU_signature,                        "([BI)C")                                              \
+  do_intrinsic(_putCharStringU,           java_lang_StringUTF16, putChar_name, putCharStringU_signature,         F_S)   \
+   do_signature(putCharStringU_signature,                        "([BII)V")                                             \
+  do_intrinsic(_compareToL,               java_lang_StringLatin1,compareTo_name, compareTo_indexOf_signature,    F_S)   \
+  do_intrinsic(_compareToU,               java_lang_StringUTF16, compareTo_name, compareTo_indexOf_signature,    F_S)   \
+  do_intrinsic(_compareToLU,              java_lang_StringLatin1,compareToLU_name, compareTo_indexOf_signature,  F_S)   \
+  do_intrinsic(_compareToUL,              java_lang_StringUTF16, compareToUL_name, compareTo_indexOf_signature,  F_S)   \
+   do_signature(compareTo_indexOf_signature,                     "([B[B)I")                                             \
    do_name(     compareTo_name,                                  "compareTo")                                           \
-  do_intrinsic(_indexOf,                  java_lang_String,       indexOf_name, string_int_signature,            F_R)   \
+   do_name(     compareToLU_name,                                "compareToUTF16")                                      \
+   do_name(     compareToUL_name,                                "compareToLatin1")                                     \
+  do_intrinsic(_indexOfL,                 java_lang_StringLatin1,indexOf_name, compareTo_indexOf_signature,      F_S)   \
+  do_intrinsic(_indexOfU,                 java_lang_StringUTF16, indexOf_name, compareTo_indexOf_signature,      F_S)   \
+  do_intrinsic(_indexOfUL,                java_lang_StringUTF16, indexOfUL_name, compareTo_indexOf_signature,    F_S)   \
+  do_intrinsic(_indexOfIL,                java_lang_StringLatin1,indexOf_name, indexOfI_signature,               F_S)   \
+  do_intrinsic(_indexOfIU,                java_lang_StringUTF16, indexOf_name, indexOfI_signature,               F_S)   \
+  do_intrinsic(_indexOfIUL,               java_lang_StringUTF16, indexOfUL_name, indexOfI_signature,             F_S)   \
+  do_intrinsic(_indexOfU_char,            java_lang_StringUTF16, indexOfChar_name, indexOfChar_signature,        F_S)   \
    do_name(     indexOf_name,                                    "indexOf")                                             \
-  do_intrinsic(_equals,                   java_lang_String,       equals_name, object_boolean_signature,         F_R)   \
+   do_name(     indexOfChar_name,                                "indexOfChar")                                         \
+   do_name(     indexOfUL_name,                                  "indexOfLatin1")                                       \
+   do_signature(indexOfI_signature,                              "([BI[BII)I")                                          \
+   do_signature(indexOfChar_signature,                           "([BIII)I")                                            \
+  do_intrinsic(_equalsL,                  java_lang_StringLatin1,equals_name, equalsB_signature,                 F_S)   \
+  do_intrinsic(_equalsU,                  java_lang_StringUTF16, equals_name, equalsB_signature,                 F_S)   \
                                                                                                                         \
   do_class(java_nio_Buffer,               "java/nio/Buffer")                                                            \
   do_intrinsic(_checkIndex,               java_nio_Buffer,        checkIndex_name, int_int_signature,            F_R)   \
    do_name(     checkIndex_name,                                 "checkIndex")                                          \
                                                                                                                         \
+  do_class(java_lang_StringCoding,        "java/lang/StringCoding")                                                     \
+  do_intrinsic(_hasNegatives,             java_lang_StringCoding, hasNegatives_name, hasNegatives_signature,     F_S)   \
+   do_name(     hasNegatives_name,                               "hasNegatives")                                        \
+   do_signature(hasNegatives_signature,                          "([BII)Z")                                             \
+                                                                                                                        \
   do_class(sun_nio_cs_iso8859_1_Encoder,  "sun/nio/cs/ISO_8859_1$Encoder")                                              \
   do_intrinsic(_encodeISOArray,     sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S)   \
    do_name(     encodeISOArray_name,                             "implEncodeISOArray")                                  \
    do_signature(encodeISOArray_signature,                        "([CI[BII)I")                                          \
                                                                                                                         \
+  do_intrinsic(_encodeByteISOArray,     java_lang_StringCoding, encodeISOArray_name, indexOfI_signature,         F_S)   \
+                                                                                                                        \
   do_class(java_math_BigInteger,                      "java/math/BigInteger")                                           \
   do_intrinsic(_multiplyToLen,      java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S)             \
    do_name(     multiplyToLen_name,                             "implMultiplyToLen")                                    \
@@ -942,24 +988,25 @@
   do_intrinsic(_updateByteBufferAdler32,  java_util_zip_Adler32,  updateByteBuffer_A_name,  updateByteBuffer_signature,  F_SN) \
    do_name(     updateByteBuffer_A_name,                          "updateByteBuffer")                                   \
                                                                                                                         \
-  /* support for sun.misc.Unsafe */                                                                                     \
-  do_class(sun_misc_Unsafe,               "sun/misc/Unsafe")                                                            \
+  /* support for Unsafe */                                                                                              \
+  do_class(sun_misc_Unsafe,                        "sun/misc/Unsafe")                                                   \
+  do_class(jdk_internal_misc_Unsafe,               "jdk/internal/misc/Unsafe")                                          \
                                                                                                                         \
-  do_intrinsic(_allocateInstance,         sun_misc_Unsafe,        allocateInstance_name, allocateInstance_signature, F_RN) \
-   do_name(     allocateInstance_name,                           "allocateInstance")                                    \
-   do_signature(allocateInstance_signature,   "(Ljava/lang/Class;)Ljava/lang/Object;")                                  \
-  do_intrinsic(_copyMemory,               sun_misc_Unsafe,        copyMemory_name, copyMemory_signature,         F_RN)  \
-   do_name(     copyMemory_name,                                 "copyMemory")                                          \
-   do_signature(copyMemory_signature,         "(Ljava/lang/Object;JLjava/lang/Object;JJ)V")                             \
-  do_intrinsic(_loadFence,                sun_misc_Unsafe,        loadFence_name, loadFence_signature,           F_RN)  \
-   do_name(     loadFence_name,                                  "loadFence")                                           \
-   do_alias(    loadFence_signature,                              void_method_signature)                                \
-  do_intrinsic(_storeFence,               sun_misc_Unsafe,        storeFence_name, storeFence_signature,         F_RN)  \
-   do_name(     storeFence_name,                                 "storeFence")                                          \
-   do_alias(    storeFence_signature,                             void_method_signature)                                \
-  do_intrinsic(_fullFence,                sun_misc_Unsafe,        fullFence_name, fullFence_signature,           F_RN)  \
-   do_name(     fullFence_name,                                  "fullFence")                                           \
-   do_alias(    fullFence_signature,                              void_method_signature)                                \
+  do_intrinsic(_allocateInstance,         jdk_internal_misc_Unsafe,     allocateInstance_name, allocateInstance_signature, F_RN) \
+   do_name(     allocateInstance_name,                                  "allocateInstance")                                      \
+   do_signature(allocateInstance_signature,                             "(Ljava/lang/Class;)Ljava/lang/Object;")                 \
+  do_intrinsic(_copyMemory,               jdk_internal_misc_Unsafe,     copyMemory_name, copyMemory_signature,         F_RN)     \
+   do_name(     copyMemory_name,                                        "copyMemory")                                            \
+   do_signature(copyMemory_signature,                                   "(Ljava/lang/Object;JLjava/lang/Object;JJ)V")            \
+  do_intrinsic(_loadFence,                jdk_internal_misc_Unsafe,     loadFence_name, loadFence_signature,           F_RN)     \
+   do_name(     loadFence_name,                                         "loadFence")                                             \
+   do_alias(    loadFence_signature,                                    void_method_signature)                                   \
+  do_intrinsic(_storeFence,               jdk_internal_misc_Unsafe,     storeFence_name, storeFence_signature,         F_RN)     \
+   do_name(     storeFence_name,                                        "storeFence")                                            \
+   do_alias(    storeFence_signature,                                   void_method_signature)                                   \
+  do_intrinsic(_fullFence,                jdk_internal_misc_Unsafe,     fullFence_name, fullFence_signature,           F_RN)     \
+   do_name(     fullFence_name,                                         "fullFence")                                             \
+   do_alias(    fullFence_signature,                                    void_method_signature)                                   \
                                                                                                                         \
   /* Custom branch frequencies profiling support for JSR292 */                                                          \
   do_class(java_lang_invoke_MethodHandleImpl,               "java/lang/invoke/MethodHandleImpl")                        \
@@ -1000,24 +1047,24 @@
   do_name(getFloat_name,"getFloat")             do_name(putFloat_name,"putFloat")                                       \
   do_name(getDouble_name,"getDouble")           do_name(putDouble_name,"putDouble")                                     \
                                                                                                                         \
-  do_intrinsic(_getObject,                sun_misc_Unsafe,        getObject_name, getObject_signature,           F_RN)  \
-  do_intrinsic(_getBoolean,               sun_misc_Unsafe,        getBoolean_name, getBoolean_signature,         F_RN)  \
-  do_intrinsic(_getByte,                  sun_misc_Unsafe,        getByte_name, getByte_signature,               F_RN)  \
-  do_intrinsic(_getShort,                 sun_misc_Unsafe,        getShort_name, getShort_signature,             F_RN)  \
-  do_intrinsic(_getChar,                  sun_misc_Unsafe,        getChar_name, getChar_signature,               F_RN)  \
-  do_intrinsic(_getInt,                   sun_misc_Unsafe,        getInt_name, getInt_signature,                 F_RN)  \
-  do_intrinsic(_getLong,                  sun_misc_Unsafe,        getLong_name, getLong_signature,               F_RN)  \
-  do_intrinsic(_getFloat,                 sun_misc_Unsafe,        getFloat_name, getFloat_signature,             F_RN)  \
-  do_intrinsic(_getDouble,                sun_misc_Unsafe,        getDouble_name, getDouble_signature,           F_RN)  \
-  do_intrinsic(_putObject,                sun_misc_Unsafe,        putObject_name, putObject_signature,           F_RN)  \
-  do_intrinsic(_putBoolean,               sun_misc_Unsafe,        putBoolean_name, putBoolean_signature,         F_RN)  \
-  do_intrinsic(_putByte,                  sun_misc_Unsafe,        putByte_name, putByte_signature,               F_RN)  \
-  do_intrinsic(_putShort,                 sun_misc_Unsafe,        putShort_name, putShort_signature,             F_RN)  \
-  do_intrinsic(_putChar,                  sun_misc_Unsafe,        putChar_name, putChar_signature,               F_RN)  \
-  do_intrinsic(_putInt,                   sun_misc_Unsafe,        putInt_name, putInt_signature,                 F_RN)  \
-  do_intrinsic(_putLong,                  sun_misc_Unsafe,        putLong_name, putLong_signature,               F_RN)  \
-  do_intrinsic(_putFloat,                 sun_misc_Unsafe,        putFloat_name, putFloat_signature,             F_RN)  \
-  do_intrinsic(_putDouble,                sun_misc_Unsafe,        putDouble_name, putDouble_signature,           F_RN)  \
+  do_intrinsic(_getObject,          jdk_internal_misc_Unsafe,     getObject_name, getObject_signature,           F_RN)  \
+  do_intrinsic(_getBoolean,         jdk_internal_misc_Unsafe,     getBoolean_name, getBoolean_signature,         F_RN)  \
+  do_intrinsic(_getByte,            jdk_internal_misc_Unsafe,     getByte_name, getByte_signature,               F_RN)  \
+  do_intrinsic(_getShort,           jdk_internal_misc_Unsafe,     getShort_name, getShort_signature,             F_RN)  \
+  do_intrinsic(_getChar,            jdk_internal_misc_Unsafe,     getChar_name, getChar_signature,               F_RN)  \
+  do_intrinsic(_getInt,             jdk_internal_misc_Unsafe,     getInt_name, getInt_signature,                 F_RN)  \
+  do_intrinsic(_getLong,            jdk_internal_misc_Unsafe,     getLong_name, getLong_signature,               F_RN)  \
+  do_intrinsic(_getFloat,           jdk_internal_misc_Unsafe,     getFloat_name, getFloat_signature,             F_RN)  \
+  do_intrinsic(_getDouble,          jdk_internal_misc_Unsafe,     getDouble_name, getDouble_signature,           F_RN)  \
+  do_intrinsic(_putObject,          jdk_internal_misc_Unsafe,     putObject_name, putObject_signature,           F_RN)  \
+  do_intrinsic(_putBoolean,         jdk_internal_misc_Unsafe,     putBoolean_name, putBoolean_signature,         F_RN)  \
+  do_intrinsic(_putByte,            jdk_internal_misc_Unsafe,     putByte_name, putByte_signature,               F_RN)  \
+  do_intrinsic(_putShort,           jdk_internal_misc_Unsafe,     putShort_name, putShort_signature,             F_RN)  \
+  do_intrinsic(_putChar,            jdk_internal_misc_Unsafe,     putChar_name, putChar_signature,               F_RN)  \
+  do_intrinsic(_putInt,             jdk_internal_misc_Unsafe,     putInt_name, putInt_signature,                 F_RN)  \
+  do_intrinsic(_putLong,            jdk_internal_misc_Unsafe,     putLong_name, putLong_signature,               F_RN)  \
+  do_intrinsic(_putFloat,           jdk_internal_misc_Unsafe,     putFloat_name, putFloat_signature,             F_RN)  \
+  do_intrinsic(_putDouble,          jdk_internal_misc_Unsafe,     putDouble_name, putDouble_signature,           F_RN)  \
                                                                                                                         \
   do_name(getObjectVolatile_name,"getObjectVolatile")   do_name(putObjectVolatile_name,"putObjectVolatile")             \
   do_name(getBooleanVolatile_name,"getBooleanVolatile") do_name(putBooleanVolatile_name,"putBooleanVolatile")           \
@@ -1029,38 +1076,38 @@
   do_name(getFloatVolatile_name,"getFloatVolatile")     do_name(putFloatVolatile_name,"putFloatVolatile")               \
   do_name(getDoubleVolatile_name,"getDoubleVolatile")   do_name(putDoubleVolatile_name,"putDoubleVolatile")             \
                                                                                                                         \
-  do_intrinsic(_getObjectVolatile,        sun_misc_Unsafe,        getObjectVolatile_name, getObject_signature,   F_RN)  \
-  do_intrinsic(_getBooleanVolatile,       sun_misc_Unsafe,        getBooleanVolatile_name, getBoolean_signature, F_RN)  \
-  do_intrinsic(_getByteVolatile,          sun_misc_Unsafe,        getByteVolatile_name, getByte_signature,       F_RN)  \
-  do_intrinsic(_getShortVolatile,         sun_misc_Unsafe,        getShortVolatile_name, getShort_signature,     F_RN)  \
-  do_intrinsic(_getCharVolatile,          sun_misc_Unsafe,        getCharVolatile_name, getChar_signature,       F_RN)  \
-  do_intrinsic(_getIntVolatile,           sun_misc_Unsafe,        getIntVolatile_name, getInt_signature,         F_RN)  \
-  do_intrinsic(_getLongVolatile,          sun_misc_Unsafe,        getLongVolatile_name, getLong_signature,       F_RN)  \
-  do_intrinsic(_getFloatVolatile,         sun_misc_Unsafe,        getFloatVolatile_name, getFloat_signature,     F_RN)  \
-  do_intrinsic(_getDoubleVolatile,        sun_misc_Unsafe,        getDoubleVolatile_name, getDouble_signature,   F_RN)  \
-  do_intrinsic(_putObjectVolatile,        sun_misc_Unsafe,        putObjectVolatile_name, putObject_signature,   F_RN)  \
-  do_intrinsic(_putBooleanVolatile,       sun_misc_Unsafe,        putBooleanVolatile_name, putBoolean_signature, F_RN)  \
-  do_intrinsic(_putByteVolatile,          sun_misc_Unsafe,        putByteVolatile_name, putByte_signature,       F_RN)  \
-  do_intrinsic(_putShortVolatile,         sun_misc_Unsafe,        putShortVolatile_name, putShort_signature,     F_RN)  \
-  do_intrinsic(_putCharVolatile,          sun_misc_Unsafe,        putCharVolatile_name, putChar_signature,       F_RN)  \
-  do_intrinsic(_putIntVolatile,           sun_misc_Unsafe,        putIntVolatile_name, putInt_signature,         F_RN)  \
-  do_intrinsic(_putLongVolatile,          sun_misc_Unsafe,        putLongVolatile_name, putLong_signature,       F_RN)  \
-  do_intrinsic(_putFloatVolatile,         sun_misc_Unsafe,        putFloatVolatile_name, putFloat_signature,     F_RN)  \
-  do_intrinsic(_putDoubleVolatile,        sun_misc_Unsafe,        putDoubleVolatile_name, putDouble_signature,   F_RN)  \
+  do_intrinsic(_getObjectVolatile,        jdk_internal_misc_Unsafe,     getObjectVolatile_name, getObject_signature,   F_RN)  \
+  do_intrinsic(_getBooleanVolatile,       jdk_internal_misc_Unsafe,     getBooleanVolatile_name, getBoolean_signature, F_RN)  \
+  do_intrinsic(_getByteVolatile,          jdk_internal_misc_Unsafe,     getByteVolatile_name, getByte_signature,       F_RN)  \
+  do_intrinsic(_getShortVolatile,         jdk_internal_misc_Unsafe,     getShortVolatile_name, getShort_signature,     F_RN)  \
+  do_intrinsic(_getCharVolatile,          jdk_internal_misc_Unsafe,     getCharVolatile_name, getChar_signature,       F_RN)  \
+  do_intrinsic(_getIntVolatile,           jdk_internal_misc_Unsafe,     getIntVolatile_name, getInt_signature,         F_RN)  \
+  do_intrinsic(_getLongVolatile,          jdk_internal_misc_Unsafe,     getLongVolatile_name, getLong_signature,       F_RN)  \
+  do_intrinsic(_getFloatVolatile,         jdk_internal_misc_Unsafe,     getFloatVolatile_name, getFloat_signature,     F_RN)  \
+  do_intrinsic(_getDoubleVolatile,        jdk_internal_misc_Unsafe,     getDoubleVolatile_name, getDouble_signature,   F_RN)  \
+  do_intrinsic(_putObjectVolatile,        jdk_internal_misc_Unsafe,     putObjectVolatile_name, putObject_signature,   F_RN)  \
+  do_intrinsic(_putBooleanVolatile,       jdk_internal_misc_Unsafe,     putBooleanVolatile_name, putBoolean_signature, F_RN)  \
+  do_intrinsic(_putByteVolatile,          jdk_internal_misc_Unsafe,     putByteVolatile_name, putByte_signature,       F_RN)  \
+  do_intrinsic(_putShortVolatile,         jdk_internal_misc_Unsafe,     putShortVolatile_name, putShort_signature,     F_RN)  \
+  do_intrinsic(_putCharVolatile,          jdk_internal_misc_Unsafe,     putCharVolatile_name, putChar_signature,       F_RN)  \
+  do_intrinsic(_putIntVolatile,           jdk_internal_misc_Unsafe,     putIntVolatile_name, putInt_signature,         F_RN)  \
+  do_intrinsic(_putLongVolatile,          jdk_internal_misc_Unsafe,     putLongVolatile_name, putLong_signature,       F_RN)  \
+  do_intrinsic(_putFloatVolatile,         jdk_internal_misc_Unsafe,     putFloatVolatile_name, putFloat_signature,     F_RN)  \
+  do_intrinsic(_putDoubleVolatile,        jdk_internal_misc_Unsafe,     putDoubleVolatile_name, putDouble_signature,   F_RN)  \
                                                                                                                         \
   do_name(getShortUnaligned_name,"getShortUnaligned")     do_name(putShortUnaligned_name,"putShortUnaligned")           \
   do_name(getCharUnaligned_name,"getCharUnaligned")       do_name(putCharUnaligned_name,"putCharUnaligned")             \
   do_name(getIntUnaligned_name,"getIntUnaligned")         do_name(putIntUnaligned_name,"putIntUnaligned")               \
   do_name(getLongUnaligned_name,"getLongUnaligned")       do_name(putLongUnaligned_name,"putLongUnaligned")             \
                                                                                                                         \
-  do_intrinsic(_getShortUnaligned,         sun_misc_Unsafe,        getShortUnaligned_name, getShort_signature,     F_R)  \
-  do_intrinsic(_getCharUnaligned,          sun_misc_Unsafe,        getCharUnaligned_name, getChar_signature,       F_R)  \
-  do_intrinsic(_getIntUnaligned,           sun_misc_Unsafe,        getIntUnaligned_name, getInt_signature,         F_R)  \
-  do_intrinsic(_getLongUnaligned,          sun_misc_Unsafe,        getLongUnaligned_name, getLong_signature,       F_R)  \
-  do_intrinsic(_putShortUnaligned,         sun_misc_Unsafe,        putShortUnaligned_name, putShort_signature,     F_R)  \
-  do_intrinsic(_putCharUnaligned,          sun_misc_Unsafe,        putCharUnaligned_name, putChar_signature,       F_R)  \
-  do_intrinsic(_putIntUnaligned,           sun_misc_Unsafe,        putIntUnaligned_name, putInt_signature,         F_R)  \
-  do_intrinsic(_putLongUnaligned,          sun_misc_Unsafe,        putLongUnaligned_name, putLong_signature,       F_R)  \
+  do_intrinsic(_getShortUnaligned,         jdk_internal_misc_Unsafe,    getShortUnaligned_name, getShort_signature,     F_R)  \
+  do_intrinsic(_getCharUnaligned,          jdk_internal_misc_Unsafe,    getCharUnaligned_name, getChar_signature,       F_R)  \
+  do_intrinsic(_getIntUnaligned,           jdk_internal_misc_Unsafe,    getIntUnaligned_name, getInt_signature,         F_R)  \
+  do_intrinsic(_getLongUnaligned,          jdk_internal_misc_Unsafe,    getLongUnaligned_name, getLong_signature,       F_R)  \
+  do_intrinsic(_putShortUnaligned,         jdk_internal_misc_Unsafe,    putShortUnaligned_name, putShort_signature,     F_R)  \
+  do_intrinsic(_putCharUnaligned,          jdk_internal_misc_Unsafe,    putCharUnaligned_name, putChar_signature,       F_R)  \
+  do_intrinsic(_putIntUnaligned,           jdk_internal_misc_Unsafe,    putIntUnaligned_name, putInt_signature,         F_R)  \
+  do_intrinsic(_putLongUnaligned,          jdk_internal_misc_Unsafe,    putLongUnaligned_name, putLong_signature,       F_R)  \
                                                                                                                         \
   /* %%% these are redundant except perhaps for getAddress, but Unsafe has native methods for them */                   \
   do_signature(getByte_raw_signature,     "(J)B")                                                                       \
@@ -1082,66 +1129,67 @@
    do_name(    getAddress_name,           "getAddress")                                                                 \
    do_name(    putAddress_name,           "putAddress")                                                                 \
                                                                                                                         \
-  do_intrinsic(_getByte_raw,              sun_misc_Unsafe,        getByte_name, getByte_raw_signature,           F_RN)  \
-  do_intrinsic(_getShort_raw,             sun_misc_Unsafe,        getShort_name, getShort_raw_signature,         F_RN)  \
-  do_intrinsic(_getChar_raw,              sun_misc_Unsafe,        getChar_name, getChar_raw_signature,           F_RN)  \
-  do_intrinsic(_getInt_raw,               sun_misc_Unsafe,        getInt_name, long_int_signature,               F_RN)  \
-  do_intrinsic(_getLong_raw,              sun_misc_Unsafe,        getLong_name, getLong_raw_signature,           F_RN)  \
-  do_intrinsic(_getFloat_raw,             sun_misc_Unsafe,        getFloat_name, getFloat_raw_signature,         F_RN)  \
-  do_intrinsic(_getDouble_raw,            sun_misc_Unsafe,        getDouble_name, getDouble_raw_signature,       F_RN)  \
-  do_intrinsic(_getAddress_raw,           sun_misc_Unsafe,        getAddress_name, getAddress_raw_signature,     F_RN)  \
-  do_intrinsic(_putByte_raw,              sun_misc_Unsafe,        putByte_name, putByte_raw_signature,           F_RN)  \
-  do_intrinsic(_putShort_raw,             sun_misc_Unsafe,        putShort_name, putShort_raw_signature,         F_RN)  \
-  do_intrinsic(_putChar_raw,              sun_misc_Unsafe,        putChar_name, putChar_raw_signature,           F_RN)  \
-  do_intrinsic(_putInt_raw,               sun_misc_Unsafe,        putInt_name, putInt_raw_signature,             F_RN)  \
-  do_intrinsic(_putLong_raw,              sun_misc_Unsafe,        putLong_name, putLong_raw_signature,           F_RN)  \
-  do_intrinsic(_putFloat_raw,             sun_misc_Unsafe,        putFloat_name, putFloat_raw_signature,         F_RN)  \
-  do_intrinsic(_putDouble_raw,            sun_misc_Unsafe,        putDouble_name, putDouble_raw_signature,       F_RN)  \
-  do_intrinsic(_putAddress_raw,           sun_misc_Unsafe,        putAddress_name, putAddress_raw_signature,     F_RN)  \
+  do_intrinsic(_getByte_raw,              jdk_internal_misc_Unsafe,     getByte_name, getByte_raw_signature,           F_R)  \
+  do_intrinsic(_getShort_raw,             jdk_internal_misc_Unsafe,     getShort_name, getShort_raw_signature,         F_R)  \
+  do_intrinsic(_getChar_raw,              jdk_internal_misc_Unsafe,     getChar_name, getChar_raw_signature,           F_R)  \
+  do_intrinsic(_getInt_raw,               jdk_internal_misc_Unsafe,     getInt_name, long_int_signature,               F_R)  \
+  do_intrinsic(_getLong_raw,              jdk_internal_misc_Unsafe,     getLong_name, getLong_raw_signature,           F_R)  \
+  do_intrinsic(_getFloat_raw,             jdk_internal_misc_Unsafe,     getFloat_name, getFloat_raw_signature,         F_R)  \
+  do_intrinsic(_getDouble_raw,            jdk_internal_misc_Unsafe,     getDouble_name, getDouble_raw_signature,       F_R)  \
+  do_intrinsic(_getAddress_raw,           jdk_internal_misc_Unsafe,     getAddress_name, getAddress_raw_signature,     F_R)  \
+  do_intrinsic(_putByte_raw,              jdk_internal_misc_Unsafe,     putByte_name, putByte_raw_signature,           F_R)  \
+  do_intrinsic(_putShort_raw,             jdk_internal_misc_Unsafe,     putShort_name, putShort_raw_signature,         F_R)  \
+  do_intrinsic(_putChar_raw,              jdk_internal_misc_Unsafe,     putChar_name, putChar_raw_signature,           F_R)  \
+  do_intrinsic(_putInt_raw,               jdk_internal_misc_Unsafe,     putInt_name, putInt_raw_signature,             F_R)  \
+  do_intrinsic(_putLong_raw,              jdk_internal_misc_Unsafe,     putLong_name, putLong_raw_signature,           F_R)  \
+  do_intrinsic(_putFloat_raw,             jdk_internal_misc_Unsafe,     putFloat_name, putFloat_raw_signature,         F_R)  \
+  do_intrinsic(_putDouble_raw,            jdk_internal_misc_Unsafe,     putDouble_name, putDouble_raw_signature,       F_R)  \
+  do_intrinsic(_putAddress_raw,           jdk_internal_misc_Unsafe,     putAddress_name, putAddress_raw_signature,     F_R)  \
                                                                                                                         \
-  do_intrinsic(_compareAndSwapObject,     sun_misc_Unsafe,        compareAndSwapObject_name, compareAndSwapObject_signature, F_RN) \
-   do_name(     compareAndSwapObject_name,                       "compareAndSwapObject")                                \
-   do_signature(compareAndSwapObject_signature,  "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z")          \
-  do_intrinsic(_compareAndSwapLong,       sun_misc_Unsafe,        compareAndSwapLong_name, compareAndSwapLong_signature, F_RN) \
-   do_name(     compareAndSwapLong_name,                         "compareAndSwapLong")                                  \
-   do_signature(compareAndSwapLong_signature,                    "(Ljava/lang/Object;JJJ)Z")                            \
-  do_intrinsic(_compareAndSwapInt,        sun_misc_Unsafe,        compareAndSwapInt_name, compareAndSwapInt_signature, F_RN) \
-   do_name(     compareAndSwapInt_name,                          "compareAndSwapInt")                                   \
-   do_signature(compareAndSwapInt_signature,                     "(Ljava/lang/Object;JII)Z")                            \
-  do_intrinsic(_putOrderedObject,         sun_misc_Unsafe,        putOrderedObject_name, putOrderedObject_signature, F_RN) \
-   do_name(     putOrderedObject_name,                           "putOrderedObject")                                    \
-   do_alias(    putOrderedObject_signature,                     /*(LObject;JLObject;)V*/ putObject_signature)           \
-  do_intrinsic(_putOrderedLong,           sun_misc_Unsafe,        putOrderedLong_name, putOrderedLong_signature, F_RN)  \
-   do_name(     putOrderedLong_name,                             "putOrderedLong")                                      \
-   do_alias(    putOrderedLong_signature,                       /*(Ljava/lang/Object;JJ)V*/ putLong_signature)          \
-  do_intrinsic(_putOrderedInt,            sun_misc_Unsafe,        putOrderedInt_name, putOrderedInt_signature,   F_RN)  \
-   do_name(     putOrderedInt_name,                              "putOrderedInt")                                       \
-   do_alias(    putOrderedInt_signature,                        /*(Ljava/lang/Object;JI)V*/ putInt_signature)           \
+  do_intrinsic(_compareAndSwapObject,     jdk_internal_misc_Unsafe,     compareAndSwapObject_name, compareAndSwapObject_signature, F_R) \
+   do_name(     compareAndSwapObject_name,                              "compareAndSwapObject")                                \
+   do_signature(compareAndSwapObject_signature,                         "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z")          \
+  do_intrinsic(_compareAndSwapLong,       jdk_internal_misc_Unsafe,     compareAndSwapLong_name, compareAndSwapLong_signature, F_R) \
+   do_name(     compareAndSwapLong_name,                                "compareAndSwapLong")                                  \
+   do_signature(compareAndSwapLong_signature,                           "(Ljava/lang/Object;JJJ)Z")                            \
+  do_intrinsic(_compareAndSwapInt,        jdk_internal_misc_Unsafe,     compareAndSwapInt_name, compareAndSwapInt_signature, F_R) \
+   do_name(     compareAndSwapInt_name,                                 "compareAndSwapInt")                                   \
+   do_signature(compareAndSwapInt_signature,                            "(Ljava/lang/Object;JII)Z")                            \
+  do_intrinsic(_putOrderedObject,         jdk_internal_misc_Unsafe,     putOrderedObject_name, putOrderedObject_signature, F_R) \
+   do_name(     putOrderedObject_name,                                  "putOrderedObject")                                    \
+   do_alias(    putOrderedObject_signature,                             /*(LObject;JLObject;)V*/ putObject_signature)           \
+  do_intrinsic(_putOrderedLong,           jdk_internal_misc_Unsafe,     putOrderedLong_name, putOrderedLong_signature, F_R)  \
+   do_name(     putOrderedLong_name,                                    "putOrderedLong")                                      \
+   do_alias(    putOrderedLong_signature,                               /*(Ljava/lang/Object;JJ)V*/ putLong_signature)          \
+  do_intrinsic(_putOrderedInt,            jdk_internal_misc_Unsafe,     putOrderedInt_name, putOrderedInt_signature,   F_R)  \
+   do_name(     putOrderedInt_name,                                     "putOrderedInt")                                       \
+   do_alias(    putOrderedInt_signature,                                 /*(Ljava/lang/Object;JI)V*/ putInt_signature)           \
                                                                                                                         \
-  do_intrinsic(_getAndAddInt,             sun_misc_Unsafe,        getAndAddInt_name, getAndAddInt_signature, F_R)       \
-   do_name(     getAndAddInt_name,                                "getAndAddInt")                                       \
-   do_signature(getAndAddInt_signature,                           "(Ljava/lang/Object;JI)I" )                           \
-  do_intrinsic(_getAndAddLong,            sun_misc_Unsafe,        getAndAddLong_name, getAndAddLong_signature, F_R)     \
-   do_name(     getAndAddLong_name,                               "getAndAddLong")                                      \
-   do_signature(getAndAddLong_signature,                          "(Ljava/lang/Object;JJ)J" )                           \
-  do_intrinsic(_getAndSetInt,             sun_misc_Unsafe,        getAndSetInt_name, getAndSetInt_signature, F_R)       \
-   do_name(     getAndSetInt_name,                                "getAndSetInt")                                       \
-   do_alias(    getAndSetInt_signature,                         /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature)   \
-  do_intrinsic(_getAndSetLong,            sun_misc_Unsafe,        getAndSetLong_name, getAndSetLong_signature, F_R)     \
-   do_name(     getAndSetLong_name,                               "getAndSetLong")                                      \
-   do_alias(    getAndSetLong_signature,                        /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature)  \
-  do_intrinsic(_getAndSetObject,          sun_misc_Unsafe,        getAndSetObject_name, getAndSetObject_signature,  F_R)\
-   do_name(     getAndSetObject_name,                             "getAndSetObject")                                    \
-   do_signature(getAndSetObject_signature,                        "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \
-                                                                                                                        \
-   /* (2) Bytecode intrinsics                                                                        */                 \
-                                                                                                                        \
-  do_intrinsic(_park,                     sun_misc_Unsafe,        park_name, park_signature,                     F_RN)  \
-   do_name(     park_name,                                       "park")                                                \
-   do_signature(park_signature,                                  "(ZJ)V")                                               \
-  do_intrinsic(_unpark,                   sun_misc_Unsafe,        unpark_name, unpark_signature,                 F_RN)  \
-   do_name(     unpark_name,                                     "unpark")                                              \
-   do_alias(    unpark_signature,                               /*(LObject;)V*/ object_void_signature)                  \
+  do_intrinsic(_getAndAddInt,             jdk_internal_misc_Unsafe,     getAndAddInt_name, getAndAddInt_signature, F_R)       \
+   do_name(     getAndAddInt_name,                                      "getAndAddInt")                                       \
+   do_signature(getAndAddInt_signature,                                 "(Ljava/lang/Object;JI)I" )                           \
+  do_intrinsic(_getAndAddLong,            jdk_internal_misc_Unsafe,     getAndAddLong_name, getAndAddLong_signature, F_R)     \
+   do_name(     getAndAddLong_name,                                     "getAndAddLong")                                      \
+   do_signature(getAndAddLong_signature,                                "(Ljava/lang/Object;JJ)J" )                           \
+  do_intrinsic(_getAndSetInt,             jdk_internal_misc_Unsafe,     getAndSetInt_name, getAndSetInt_signature, F_R)       \
+   do_name(     getAndSetInt_name,                                      "getAndSetInt")                                       \
+   do_alias(    getAndSetInt_signature,                                 /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature)   \
+  do_intrinsic(_getAndSetLong,            jdk_internal_misc_Unsafe,     getAndSetLong_name, getAndSetLong_signature, F_R)     \
+   do_name(     getAndSetLong_name,                                     "getAndSetLong")                                      \
+   do_alias(    getAndSetLong_signature,                                /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature)  \
+  do_intrinsic(_getAndSetObject,          jdk_internal_misc_Unsafe,     getAndSetObject_name, getAndSetObject_signature,  F_R)\
+   do_name(     getAndSetObject_name,                                   "getAndSetObject")                                    \
+   do_signature(getAndSetObject_signature,                              "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \
+                                                                                                                               \
+   /* (2) Bytecode intrinsics                                                                        */                        \
+                                                                                                                               \
+  do_intrinsic(_park,                     jdk_internal_misc_Unsafe,     park_name, park_signature,                     F_R)    \
+   do_name(     park_name,                                              "park")                                                \
+   do_signature(park_signature,                                         "(ZJ)V")                                               \
+  do_intrinsic(_unpark,                   jdk_internal_misc_Unsafe,     unpark_name, unpark_signature,                 F_R)    \
+   do_name(     unpark_name,                                            "unpark")                                              \
+   do_alias(    unpark_signature,                                       /*(LObject;)V*/ object_void_signature)                 \
+                                                                                                                               \
   do_intrinsic(_StringBuilder_void,   java_lang_StringBuilder, object_initializer_name, void_method_signature,     F_R)   \
   do_intrinsic(_StringBuilder_int,    java_lang_StringBuilder, object_initializer_name, int_void_signature,        F_R)   \
   do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature,     F_R)   \
@@ -1406,7 +1454,7 @@
 
   // Returns true if a compiler intrinsic is disabled by command-line flags
   // and false otherwise.
-  static bool is_disabled_by_flags(methodHandle method);
+  static bool is_disabled_by_flags(const methodHandle& method);
 };
 
 #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
--- a/hotspot/src/share/vm/code/compiledIC.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/code/compiledIC.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -462,7 +462,7 @@
 // is_optimized: Compiler has generated an optimized call (i.e., no inline
 // cache) static_bound: The call can be static bound (i.e, no need to use
 // inline cache)
-void CompiledIC::compute_monomorphic_entry(methodHandle method,
+void CompiledIC::compute_monomorphic_entry(const methodHandle& method,
                                            KlassHandle receiver_klass,
                                            bool is_optimized,
                                            bool static_bound,
@@ -594,7 +594,7 @@
 
 // Compute settings for a CompiledStaticCall. Since we might have to set
 // the stub when calling to the interpreter, we need to return arguments.
-void CompiledStaticCall::compute_entry(methodHandle m, StaticCallInfo& info) {
+void CompiledStaticCall::compute_entry(const methodHandle& m, StaticCallInfo& info) {
   nmethod* m_code = m->code();
   info._callee = m;
   if (m_code != NULL && m_code->is_in_use()) {
--- a/hotspot/src/share/vm/code/compiledIC.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/code/compiledIC.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -222,7 +222,7 @@
   // allocation in the code cache fails.
   bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS);
 
-  static void compute_monomorphic_entry(methodHandle method, KlassHandle receiver_klass,
+  static void compute_monomorphic_entry(const methodHandle& method, KlassHandle receiver_klass,
                                         bool is_optimized, bool static_bound, CompiledICInfo& info, TRAPS);
 
   // Location
@@ -324,7 +324,7 @@
   void set(const StaticCallInfo& info);
 
   // Compute entry point given a method
-  static void compute_entry(methodHandle m, StaticCallInfo& info);
+  static void compute_entry(const methodHandle& m, StaticCallInfo& info);
 
   // Stub support
   address find_stub();
--- a/hotspot/src/share/vm/code/debugInfoRec.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/code/debugInfoRec.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -324,7 +324,7 @@
 // must call add_safepoint before: it sets PcDesc and this routine uses
 // the last PcDesc set
 void DebugInformationRecorder::describe_scope(int         pc_offset,
-                                              methodHandle methodH,
+                                              const methodHandle& methodH,
                                               ciMethod*   method,
                                               int         bci,
                                               bool        reexecute,
--- a/hotspot/src/share/vm/code/debugInfoRec.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/code/debugInfoRec.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,7 @@
   // by add_non_safepoint, and the locals, expressions, and monitors
   // must all be null.
   void describe_scope(int         pc_offset,
-                      methodHandle methodH,
+                      const methodHandle& methodH,
                       ciMethod*   method,
                       int         bci,
                       bool        reexecute,
--- a/hotspot/src/share/vm/code/dependencies.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/code/dependencies.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -151,7 +151,7 @@
 }
 
 void Dependencies::assert_leaf_type(Klass* ctxk) {
-  if (ctxk->oop_is_array()) {
+  if (ctxk->is_array_klass()) {
     // As a special case, support this assertion on an array type,
     // which reduces to an assertion on its element type.
     // Note that this cannot be done with assertions that
@@ -1084,10 +1084,10 @@
       return true;  // Must punt the assertion to true.
     Klass* k = ctxk;
     Method* lm = k->lookup_method(m->name(), m->signature());
-    if (lm == NULL && k->oop_is_instance()) {
+    if (lm == NULL && k->is_instance_klass()) {
       // It might be an interface method
-        lm = ((InstanceKlass*)k)->lookup_method_in_ordered_interfaces(m->name(),
-                                                                m->signature());
+      lm = InstanceKlass::cast(k)->lookup_method_in_ordered_interfaces(m->name(),
+                                                                 m->signature());
     }
     if (lm == m)
       // Method m is inherited into ctxk.
@@ -1135,7 +1135,7 @@
   bool is_witness(Klass* k) {
     if (doing_subtype_search()) {
       return Dependencies::is_concrete_klass(k);
-    } else if (!k->oop_is_instance()) {
+    } else if (!k->is_instance_klass()) {
       return false; // no methods to find in an array type
     } else {
       // Search class hierarchy first.
@@ -1840,20 +1840,20 @@
     Klass* k = str.klass();
     switch (str.change_type()) {
     case Change_new_type:
-      tty->print_cr("  dependee = %s", InstanceKlass::cast(k)->external_name());
+      tty->print_cr("  dependee = %s", k->external_name());
       break;
     case Change_new_sub:
       if (!WizardMode) {
         ++nsup;
       } else {
-        tty->print_cr("  context super = %s", InstanceKlass::cast(k)->external_name());
+        tty->print_cr("  context super = %s", k->external_name());
       }
       break;
     case Change_new_impl:
       if (!WizardMode) {
         ++nint;
       } else {
-        tty->print_cr("  context interface = %s", InstanceKlass::cast(k)->external_name());
+        tty->print_cr("  context interface = %s", k->external_name());
       }
       break;
     }
@@ -1885,7 +1885,7 @@
   case Change_new_sub:
     // 6598190: brackets workaround Sun Studio C++ compiler bug 6629277
     {
-      _klass = InstanceKlass::cast(_klass)->super();
+      _klass = _klass->super();
       if (_klass != NULL) {
         return true;
       }
@@ -1931,7 +1931,7 @@
 }
 
 bool KlassDepChange::involves_context(Klass* k) {
-  if (k == NULL || !k->oop_is_instance()) {
+  if (k == NULL || !k->is_instance_klass()) {
     return false;
   }
   InstanceKlass* ik = InstanceKlass::cast(k);
--- a/hotspot/src/share/vm/code/dependencies.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/code/dependencies.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -351,7 +351,7 @@
 #if INCLUDE_JVMCI
  private:
   static void check_ctxk(Klass* ctxk) {
-    assert(ctxk->oop_is_instance(), "java types only");
+    assert(ctxk->is_instance_klass(), "java types only");
   }
   static void check_ctxk_abstract(Klass* ctxk) {
     check_ctxk(ctxk);
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -558,7 +558,7 @@
 #endif
 }
 
-nmethod* nmethod::new_native_nmethod(methodHandle method,
+nmethod* nmethod::new_native_nmethod(const methodHandle& method,
   int compile_id,
   CodeBuffer *code_buffer,
   int vep_offset,
@@ -593,7 +593,7 @@
   return nm;
 }
 
-nmethod* nmethod::new_nmethod(methodHandle method,
+nmethod* nmethod::new_nmethod(const methodHandle& method,
   int compile_id,
   int entry_bci,
   CodeOffsets* offsets,
@@ -1350,20 +1350,17 @@
   // Unregister must be done before the state change
   Universe::heap()->unregister_nmethod(this);
 
+  _state = unloaded;
+
 #if INCLUDE_JVMCI
   // The method can only be unloaded after the pointer to the installed code
   // Java wrapper is no longer alive. Here we need to clear out this weak
   // reference to the dead object. Nulling out the reference has to happen
   // after the method is unregistered since the original value may be still
   // tracked by the rset.
-  if (_jvmci_installed_code != NULL) {
-    InstalledCode::set_address(_jvmci_installed_code, 0);
-    _jvmci_installed_code = NULL;
-  }
+  maybe_invalidate_installed_code();
 #endif
 
-  _state = unloaded;
-
   // Log the unloading.
   log_state_change();
 
@@ -1525,12 +1522,8 @@
   } else {
     assert(state == not_entrant, "other cases may need to be handled differently");
   }
-#if INCLUDE_JVMCI
-  if (_jvmci_installed_code != NULL) {
-    // Break the link between nmethod and InstalledCode such that the nmethod can subsequently be flushed safely.
-    InstalledCode::set_address(_jvmci_installed_code, 0);
-  }
-#endif
+
+  JVMCI_ONLY(maybe_invalidate_installed_code());
 
   if (TraceCreateZombies) {
     ResourceMark m;
@@ -1615,7 +1608,11 @@
         // During GC the is_alive closure is non-NULL, and is used to
         // determine liveness of dependees that need to be updated.
         if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
-          InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
+          // The GC defers deletion of this entry, since there might be multiple threads
+          // iterating over the _dependencies graph. Other call paths are single-threaded
+          // and may delete it immediately.
+          bool delete_immediately = is_alive == NULL;
+          InstanceKlass::cast(klass)->remove_dependent_nmethod(this, delete_immediately);
         }
       }
     }
@@ -3004,7 +3001,7 @@
     deps.print_dependency();
     Klass* ctxk = deps.context_type();
     if (ctxk != NULL) {
-      if (ctxk->oop_is_instance() && ((InstanceKlass*)ctxk)->is_dependent_nmethod(this)) {
+      if (ctxk->is_instance_klass() && InstanceKlass::cast(ctxk)->is_dependent_nmethod(this)) {
         tty->print_cr("   [nmethod<=klass]%s", ctxk->external_name());
       }
     }
@@ -3384,6 +3381,22 @@
 #endif // !PRODUCT
 
 #if INCLUDE_JVMCI
+void nmethod::maybe_invalidate_installed_code() {
+  if (_jvmci_installed_code != NULL) {
+     if (!is_alive()) {
+       // Break the link between nmethod and InstalledCode such that the nmethod
+       // can subsequently be flushed safely.  The link must be maintained while
+       // the method could have live activations since invalidateInstalledCode
+       // might want to invalidate all existing activations.
+       InstalledCode::set_address(_jvmci_installed_code, 0);
+       InstalledCode::set_entryPoint(_jvmci_installed_code, 0);
+       _jvmci_installed_code = NULL;
+     } else if (is_not_entrant()) {
+       InstalledCode::set_entryPoint(_jvmci_installed_code, 0);
+     }
+  }
+}
+
 char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
   if (!this->is_compiled_by_jvmci()) {
     return NULL;
--- a/hotspot/src/share/vm/code/nmethod.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -307,7 +307,7 @@
 
  public:
   // create nmethod with entry_bci
-  static nmethod* new_nmethod(methodHandle method,
+  static nmethod* new_nmethod(const methodHandle& method,
                               int compile_id,
                               int entry_bci,
                               CodeOffsets* offsets,
@@ -327,7 +327,7 @@
 #endif
                              );
 
-  static nmethod* new_native_nmethod(methodHandle method,
+  static nmethod* new_native_nmethod(const methodHandle& method,
                                      int compile_id,
                                      CodeBuffer *code_buffer,
                                      int vep_offset,
@@ -603,6 +603,7 @@
   oop jvmci_installed_code() { return _jvmci_installed_code ; }
   char* jvmci_installed_code_name(char* buf, size_t buflen);
   void set_jvmci_installed_code(oop installed_code) { _jvmci_installed_code = installed_code;  }
+  void maybe_invalidate_installed_code();
   oop speculation_log() { return _speculation_log ; }
   void set_speculation_log(oop speculation_log) { _speculation_log = speculation_log;  }
 #endif
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -111,7 +111,7 @@
   // Missing feature tests
   virtual bool supports_native()                 { return true; }
   virtual bool supports_osr   ()                 { return true; }
-  virtual bool can_compile_method(methodHandle method)  { return true; }
+  virtual bool can_compile_method(const methodHandle& method)  { return true; }
 
   // Determine if the current compiler provides an intrinsic
   // for method 'method'. An intrinsic is available if:
@@ -138,7 +138,7 @@
   // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
   // for more details.
 
-  virtual bool is_intrinsic_available(methodHandle method, DirectiveSet* directive) {
+  virtual bool is_intrinsic_available(const methodHandle& method, DirectiveSet* directive) {
     return is_intrinsic_supported(method) &&
            !directive->is_intrinsic_disabled(method) &&
            !vmIntrinsics::is_disabled_by_flags(method);
@@ -152,7 +152,7 @@
   // by default no intrinsics are supported by a compiler except
   // the ones listed in the method. Overriding methods should conform
   // to this behavior.
-  virtual bool is_intrinsic_supported(methodHandle method) {
+  virtual bool is_intrinsic_supported(const methodHandle& method) {
     return false;
   }
 
@@ -162,6 +162,9 @@
   bool is_jvmci()                                { return _type == jvmci; }
   bool is_shark()                                { return _type == shark; }
 
+  // Extra tests to identify trivial methods for the tiered compilation policy.
+  virtual bool is_trivial(Method* method) { return false; }
+
   // Customization
   virtual void initialize () = 0;
 
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -790,10 +790,10 @@
 // CompileBroker::compile_method
 //
 // Request compilation of a method.
-void CompileBroker::compile_method_base(methodHandle method,
+void CompileBroker::compile_method_base(const methodHandle& method,
                                         int osr_bci,
                                         int comp_level,
-                                        methodHandle hot_method,
+                                        const methodHandle& hot_method,
                                         int hot_count,
                                         const char* comment,
                                         Thread* thread) {
@@ -803,7 +803,7 @@
   }
 
   guarantee(!method->is_abstract(), "cannot compile abstract methods");
-  assert(method->method_holder()->oop_is_instance(),
+  assert(method->method_holder()->is_instance_klass(),
          "sanity check");
   assert(!method->method_holder()->is_not_initialized(),
          "method holder must be initialized");
@@ -993,12 +993,12 @@
 }
 
 
-nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci,
+nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
                                        int comp_level,
-                                       methodHandle hot_method, int hot_count,
+                                       const methodHandle& hot_method, int hot_count,
                                        const char* comment, Thread* THREAD) {
   // make sure arguments make sense
-  assert(method->method_holder()->oop_is_instance(), "not an instance method");
+  assert(method->method_holder()->is_instance_klass(), "not an instance method");
   assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
   assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods");
   assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
@@ -1134,9 +1134,9 @@
 // CompileBroker::compilation_is_complete
 //
 // See if compilation of this method is already complete.
-bool CompileBroker::compilation_is_complete(methodHandle method,
-                                            int          osr_bci,
-                                            int          comp_level) {
+bool CompileBroker::compilation_is_complete(const methodHandle& method,
+                                            int                 osr_bci,
+                                            int                 comp_level) {
   bool is_osr = (osr_bci != standard_entry_bci);
   if (is_osr) {
     if (method->is_not_osr_compilable(comp_level)) {
@@ -1167,7 +1167,7 @@
  * versa).  This can be remedied by a full queue search to disambiguate
  * cases.  If it is deemed profitable, this may be done.
  */
-bool CompileBroker::compilation_is_in_queue(methodHandle method) {
+bool CompileBroker::compilation_is_in_queue(const methodHandle& method) {
   return method->queued_for_compilation();
 }
 
@@ -1175,7 +1175,7 @@
 // CompileBroker::compilation_is_prohibited
 //
 // See if this compilation is not allowed.
-bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level) {
+bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level) {
   bool is_native = method->is_native();
   // Some compilers may not support the compilation of natives.
   AbstractCompiler *comp = compiler(comp_level);
@@ -1222,7 +1222,7 @@
  * and the ID is not within the specified range, the method is not compiled and 0 is returned.
  * The function also allows to generate separate compilation IDs for OSR compilations.
  */
-int CompileBroker::assign_compile_id(methodHandle method, int osr_bci) {
+int CompileBroker::assign_compile_id(const methodHandle& method, int osr_bci) {
 #ifdef ASSERT
   bool is_osr = (osr_bci != standard_entry_bci);
   int id;
@@ -1257,7 +1257,7 @@
 // CompileBroker::assign_compile_id_unlocked
 //
 // Public wrapper for assign_compile_id that acquires the needed locks
-uint CompileBroker::assign_compile_id_unlocked(Thread* thread, methodHandle method, int osr_bci) {
+uint CompileBroker::assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci) {
   MutexLocker locker(MethodCompileQueue_lock, thread);
   return assign_compile_id(method, osr_bci);
 }
@@ -1274,7 +1274,7 @@
 
 // ------------------------------------------------------------------
 // CompileBroker::preload_classes
-void CompileBroker::preload_classes(methodHandle method, TRAPS) {
+void CompileBroker::preload_classes(const methodHandle& method, TRAPS) {
   // Move this code over from c1_Compiler.cpp
   ShouldNotReachHere();
 }
@@ -1285,15 +1285,15 @@
 //
 // Create a CompileTask object representing the current request for
 // compilation.  Add this task to the queue.
-CompileTask* CompileBroker::create_compile_task(CompileQueue* queue,
-                                              int           compile_id,
-                                              methodHandle  method,
-                                              int           osr_bci,
-                                              int           comp_level,
-                                              methodHandle  hot_method,
-                                              int           hot_count,
-                                              const char*   comment,
-                                              bool          blocking) {
+CompileTask* CompileBroker::create_compile_task(CompileQueue*       queue,
+                                                int                 compile_id,
+                                                const methodHandle& method,
+                                                int                 osr_bci,
+                                                int                 comp_level,
+                                                const methodHandle& hot_method,
+                                                int                 hot_count,
+                                                const char*         comment,
+                                                bool                blocking) {
   CompileTask* new_task = CompileTask::allocate();
   new_task->initialize(compile_id, method, osr_bci, comp_level,
                        hot_method, hot_count, comment,
@@ -1891,7 +1891,7 @@
 // CompileBroker::set_last_compile
 //
 // Record this compilation for debugging purposes.
-void CompileBroker::set_last_compile(CompilerThread* thread, methodHandle method, bool is_osr, int comp_level) {
+void CompileBroker::set_last_compile(CompilerThread* thread, const methodHandle& method, bool is_osr, int comp_level) {
   ResourceMark rm;
   char* method_name = method->name()->as_C_string();
   strncpy(_last_method_compiled, method_name, CompileBroker::name_buffer_length);
@@ -2242,4 +2242,3 @@
   st->cr();
 #endif
 }
-
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -145,7 +145,7 @@
 
   // Compile type Information for print_last_compile() and CompilerCounters
   enum { no_compile, normal_compile, osr_compile, native_compile };
-  static int assign_compile_id (methodHandle method, int osr_bci);
+  static int assign_compile_id (const methodHandle& method, int osr_bci);
 
 
  private:
@@ -218,33 +218,33 @@
 
   static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS);
   static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count);
-  static bool compilation_is_complete  (methodHandle method, int osr_bci, int comp_level);
-  static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level);
+  static bool compilation_is_complete  (const methodHandle& method, int osr_bci, int comp_level);
+  static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level);
   static bool is_compile_blocking();
-  static void preload_classes          (methodHandle method, TRAPS);
+  static void preload_classes          (const methodHandle& method, TRAPS);
 
-  static CompileTask* create_compile_task(CompileQueue* queue,
-                                          int           compile_id,
-                                          methodHandle  method,
-                                          int           osr_bci,
-                                          int           comp_level,
-                                          methodHandle  hot_method,
-                                          int           hot_count,
-                                          const char*   comment,
-                                          bool          blocking);
+  static CompileTask* create_compile_task(CompileQueue*       queue,
+                                          int                 compile_id,
+                                          const methodHandle& method,
+                                          int                 osr_bci,
+                                          int                 comp_level,
+                                          const methodHandle& hot_method,
+                                          int                 hot_count,
+                                          const char*         comment,
+                                          bool                blocking);
   static void wait_for_completion(CompileTask* task);
 
   static void invoke_compiler_on_method(CompileTask* task);
   static void post_compile(CompilerThread* thread, CompileTask* task, EventCompilation& event, bool success, ciEnv* ci_env);
-  static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level);
+  static void set_last_compile(CompilerThread *thread, const methodHandle& method, bool is_osr, int comp_level);
   static void push_jni_handle_block();
   static void pop_jni_handle_block();
   static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
 
-  static void compile_method_base(methodHandle method,
+  static void compile_method_base(const methodHandle& method,
                                   int osr_bci,
                                   int comp_level,
-                                  methodHandle hot_method,
+                                  const methodHandle& hot_method,
                                   int hot_count,
                                   const char* comment,
                                   Thread* thread);
@@ -269,7 +269,7 @@
     return NULL;
   }
 
-  static bool compilation_is_in_queue(methodHandle method);
+  static bool compilation_is_in_queue(const methodHandle& method);
   static void print_compile_queues(outputStream* st);
   static void print_directives(outputStream* st);
   static int queue_size(int comp_level) {
@@ -278,15 +278,15 @@
   }
   static void compilation_init();
   static void init_compiler_thread_log();
-  static nmethod* compile_method(methodHandle method,
+  static nmethod* compile_method(const methodHandle& method,
                                  int osr_bci,
                                  int comp_level,
-                                 methodHandle hot_method,
+                                 const methodHandle& hot_method,
                                  int hot_count,
                                  const char* comment, Thread* thread);
 
   // Acquire any needed locks and assign a compile id
-  static uint assign_compile_id_unlocked(Thread* thread, methodHandle method, int osr_bci);
+  static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci);
 
   static void compiler_thread_loop();
   static uint get_compilation_id() { return _compilation_id; }
--- a/hotspot/src/share/vm/compiler/compileTask.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileTask.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,10 +76,10 @@
 
 
 void CompileTask::initialize(int compile_id,
-                             methodHandle method,
+                             const methodHandle& method,
                              int osr_bci,
                              int comp_level,
-                             methodHandle hot_method,
+                             const methodHandle& hot_method,
                              int hot_count,
                              const char* comment,
                              bool is_blocking) {
--- a/hotspot/src/share/vm/compiler/compileTask.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compileTask.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -71,8 +71,8 @@
     _lock = new Monitor(Mutex::nonleaf+2, "CompileTaskLock");
   }
 
-  void initialize(int compile_id, methodHandle method, int osr_bci, int comp_level,
-                  methodHandle hot_method, int hot_count, const char* comment,
+  void initialize(int compile_id, const methodHandle& method, int osr_bci, int comp_level,
+                  const methodHandle& hot_method, int hot_count, const char* comment,
                   bool is_blocking);
 
   static CompileTask* allocate();
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -317,7 +317,7 @@
 }
 
 template<typename T>
-bool CompilerOracle::has_option_value(methodHandle method, const char* option, T& value) {
+bool CompilerOracle::has_option_value(const methodHandle& method, const char* option, T& value) {
   if (option_list != NULL) {
     TypedMethodOptionMatcher* m = option_list->match(method, option, get_type_for<T>());
     if (m != NULL) {
@@ -333,19 +333,19 @@
 }
 
 // Explicit instantiation for all OptionTypes supported.
-template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
-template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
-template bool CompilerOracle::has_option_value<bool>(methodHandle method, const char* option, bool& value);
-template bool CompilerOracle::has_option_value<ccstr>(methodHandle method, const char* option, ccstr& value);
-template bool CompilerOracle::has_option_value<double>(methodHandle method, const char* option, double& value);
+template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, const char* option, intx& value);
+template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, const char* option, uintx& value);
+template bool CompilerOracle::has_option_value<bool>(const methodHandle& method, const char* option, bool& value);
+template bool CompilerOracle::has_option_value<ccstr>(const methodHandle& method, const char* option, ccstr& value);
+template bool CompilerOracle::has_option_value<double>(const methodHandle& method, const char* option, double& value);
 
-bool CompilerOracle::has_option_string(methodHandle method, const char* option) {
+bool CompilerOracle::has_option_string(const methodHandle& method, const char* option) {
   bool value = false;
   has_option_value(method, option, value);
   return value;
 }
 
-bool CompilerOracle::should_exclude(methodHandle method) {
+bool CompilerOracle::should_exclude(const methodHandle& method) {
   if (check_predicate(ExcludeCommand, method)) {
     return true;
   }
@@ -355,15 +355,15 @@
   return false;
 }
 
-bool CompilerOracle::should_inline(methodHandle method) {
+bool CompilerOracle::should_inline(const methodHandle& method) {
   return (check_predicate(InlineCommand, method));
 }
 
-bool CompilerOracle::should_not_inline(methodHandle method) {
+bool CompilerOracle::should_not_inline(const methodHandle& method) {
   return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method);
 }
 
-bool CompilerOracle::should_print(methodHandle method) {
+bool CompilerOracle::should_print(const methodHandle& method) {
   return check_predicate(PrintCommand, method);
 }
 
@@ -371,13 +371,13 @@
   return lists[PrintCommand] != NULL;
 }
 
-bool CompilerOracle::should_log(methodHandle method) {
+bool CompilerOracle::should_log(const methodHandle& method) {
   if (!LogCompilation)            return false;
   if (lists[LogCommand] == NULL)  return true;  // by default, log all
   return (check_predicate(LogCommand, method));
 }
 
-bool CompilerOracle::should_break_at(methodHandle method) {
+bool CompilerOracle::should_break_at(const methodHandle& method) {
   return check_predicate(BreakCommand, method);
 }
 
@@ -757,7 +757,7 @@
   stream.cr();
 }
 
-void CompilerOracle::append_exclude_to_file(methodHandle method) {
+void CompilerOracle::append_exclude_to_file(const methodHandle& method) {
   assert(has_command_file(), "command file must be specified");
   fileStream stream(fopen(cc_file(), "at"));
   stream.print("exclude ");
--- a/hotspot/src/share/vm/compiler/compilerOracle.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,31 +46,31 @@
   static void parse_from_file();
 
   // Tells whether we to exclude compilation of method
-  static bool should_exclude(methodHandle method);
+  static bool should_exclude(const methodHandle& method);
   static bool should_exclude_quietly() { return _quiet; }
 
   // Tells whether we want to inline this method
-  static bool should_inline(methodHandle method);
+  static bool should_inline(const methodHandle& method);
 
   // Tells whether we want to disallow inlining of this method
-  static bool should_not_inline(methodHandle method);
+  static bool should_not_inline(const methodHandle& method);
 
   // Tells whether we should print the assembly for this method
-  static bool should_print(methodHandle method);
+  static bool should_print(const methodHandle& method);
 
   // Tells whether we should log the compilation data for this method
-  static bool should_log(methodHandle method);
+  static bool should_log(const methodHandle& method);
 
   // Tells whether to break when compiling method
-  static bool should_break_at(methodHandle method);
+  static bool should_break_at(const methodHandle& method);
 
   // Check to see if this method has option set for it
-  static bool has_option_string(methodHandle method, const char * option);
+  static bool has_option_string(const methodHandle& method, const char * option);
 
   // Check if method has option and value set. If yes, overwrite value and return true,
   // otherwise leave value unchanged and return false.
   template<typename T>
-  static bool has_option_value(methodHandle method, const char* option, T& value);
+  static bool has_option_value(const methodHandle& method, const char* option, T& value);
 
   // Fast check if there is any option available that compile control needs to know about
   static bool has_any_option();
@@ -83,7 +83,7 @@
 
   // For updating the oracle file
   static void append_comment_to_file(const char* message);
-  static void append_exclude_to_file(methodHandle method);
+  static void append_exclude_to_file(const methodHandle& method);
 
   // Tells whether there are any methods to print for print_method_statistics()
   static bool should_print_methods();
--- a/hotspot/src/share/vm/compiler/disassembler.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/disassembler.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -86,6 +86,12 @@
   os::jvm_path(buf, sizeof(buf));
   int jvm_offset = -1;
   int lib_offset = -1;
+#ifdef STATIC_BUILD
+  char* p = strrchr(buf, '/');
+  *p = '\0';
+  strcat(p, "/lib/");
+  lib_offset = jvm_offset = strlen(buf);
+#else
   {
     // Match "jvm[^/]*" in jvm_path.
     const char* base = buf;
@@ -94,6 +100,7 @@
     p = strstr(p ? p : base, "jvm");
     if (p != NULL)  jvm_offset = p - base;
   }
+#endif
   // Find the disassembler shared library.
   // Search for several paths derived from libjvm, in this order:
   // 1. <home>/jre/lib/<arch>/<vm>/libhsdis-<arch>.so  (for compatibility)
--- a/hotspot/src/share/vm/compiler/methodMatcher.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/methodMatcher.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -306,7 +306,7 @@
   }
 }
 
-bool MethodMatcher::matches(methodHandle method) const {
+bool MethodMatcher::matches(const methodHandle& method) const {
   Symbol* class_name  = method->method_holder()->name();
   Symbol* method_name = method->name();
   Symbol* signature = method->signature();
@@ -362,7 +362,7 @@
   return bm;
 }
 
-bool BasicMatcher::match(methodHandle method) {
+bool BasicMatcher::match(const methodHandle& method) {
   for (BasicMatcher* current = this; current != NULL; current = current->next()) {
     if (current->matches(method)) {
       return true;
@@ -391,7 +391,7 @@
   return im;
 }
 
-bool InlineMatcher::match(methodHandle method, int inline_action) {
+bool InlineMatcher::match(const methodHandle& method, int inline_action) {
   for (InlineMatcher* current = this; current != NULL; current = current->next()) {
     if (current->matches(method)) {
       return (current->_inline_action == inline_action);
--- a/hotspot/src/share/vm/compiler/methodMatcher.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/methodMatcher.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -60,7 +60,7 @@
   void init(Symbol* class_name, Mode class_mode, Symbol* method_name, Mode method_mode, Symbol* signature);
   static void parse_method_pattern(char*& line, const char*& error_msg, MethodMatcher* m);
   static void print_symbol(outputStream* st, Symbol* h, Mode mode);
-  bool matches(methodHandle method) const;
+  bool matches(const methodHandle& method) const;
   void print_base(outputStream* st);
 
  private:
@@ -82,7 +82,7 @@
   }
 
   static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg);
-  bool match(methodHandle method);
+  bool match(const methodHandle& method);
   void set_next(BasicMatcher* next) { _next = next; }
   BasicMatcher* next() { return _next; }
 
@@ -113,7 +113,7 @@
 
 public:
   static InlineMatcher* parse_method_pattern(char* line, const char*& error_msg);
-  bool match(methodHandle method, int inline_action);
+  bool match(const methodHandle& method, int inline_action);
   void print(outputStream* st);
   void set_next(InlineMatcher* next) { _next = next; }
   InlineMatcher* next() { return _next; }
--- a/hotspot/src/share/vm/compiler/oopMap.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/compiler/oopMap.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -73,8 +73,8 @@
 
   // Constructors
   OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); }
-  OopMapValue (VMReg reg, oop_types t) { set_reg_type(reg,t); }
-  OopMapValue (VMReg reg, oop_types t, VMReg reg2) { set_reg_type(reg,t); set_content_reg(reg2); }
+  OopMapValue (VMReg reg, oop_types t) { set_reg_type(reg, t); set_content_reg(VMRegImpl::Bad()); }
+  OopMapValue (VMReg reg, oop_types t, VMReg reg2) { set_reg_type(reg, t); set_content_reg(reg2); }
   OopMapValue (CompressedReadStream* stream) { read_from(stream); }
 
   // Archiving
@@ -87,7 +87,7 @@
 
   void read_from(CompressedReadStream* stream) {
     set_value(stream->read_int());
-    if(is_callee_saved() || is_derived_oop()) {
+    if (is_callee_saved() || is_derived_oop()) {
       set_content_reg(VMRegImpl::as_VMReg(stream->read_int(), true));
     }
   }
--- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -73,11 +73,7 @@
 }
 
 // Constructor
-CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
-  MemRegion mr, bool use_adaptive_freelists,
-  FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
-  _dictionaryChoice(dictionaryChoice),
-  _adaptive_freelists(use_adaptive_freelists),
+CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr) :
   _bt(bs, mr),
   // free list locks are in the range of values taken by _lockRank
   // This range currently is [_leaf+2, _leaf+3]
@@ -100,48 +96,17 @@
          "FreeChunk is larger than expected");
   _bt.set_space(this);
   initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle);
-  // We have all of "mr", all of which we place in the dictionary
-  // as one big chunk. We'll need to decide here which of several
-  // possible alternative dictionary implementations to use. For
-  // now the choice is easy, since we have only one working
-  // implementation, namely, the simple binary tree (splaying
-  // temporarily disabled).
-  switch (dictionaryChoice) {
-    case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree:
-      _dictionary = new AFLBinaryTreeDictionary(mr);
-      break;
-    case FreeBlockDictionary<FreeChunk>::dictionarySplayTree:
-    case FreeBlockDictionary<FreeChunk>::dictionarySkipList:
-    default:
-      warning("dictionaryChoice: selected option not understood; using"
-              " default BinaryTreeDictionary implementation instead.");
-  }
+
+  _dictionary = new AFLBinaryTreeDictionary(mr);
+
   assert(_dictionary != NULL, "CMS dictionary initialization");
   // The indexed free lists are initially all empty and are lazily
   // filled in on demand. Initialize the array elements to NULL.
   initializeIndexedFreeListArray();
 
-  // Not using adaptive free lists assumes that allocation is first
-  // from the linAB's.  Also a cms perm gen which can be compacted
-  // has to have the klass's klassKlass allocated at a lower
-  // address in the heap than the klass so that the klassKlass is
-  // moved to its new location before the klass is moved.
-  // Set the _refillSize for the linear allocation blocks
-  if (!use_adaptive_freelists) {
-    FreeChunk* fc = _dictionary->get_chunk(mr.word_size(),
-                                           FreeBlockDictionary<FreeChunk>::atLeast);
-    // The small linAB initially has all the space and will allocate
-    // a chunk of any size.
-    HeapWord* addr = (HeapWord*) fc;
-    _smallLinearAllocBlock.set(addr, fc->size() ,
-      1024*SmallForLinearAlloc, fc->size());
-    // Note that _unallocated_block is not updated here.
-    // Allocations from the linear allocation block should
-    // update it.
-  } else {
-    _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc,
-                               SmallForLinearAlloc);
-  }
+  _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc,
+                             SmallForLinearAlloc);
+
   // CMSIndexedFreeListReplenish should be at least 1
   CMSIndexedFreeListReplenish = MAX2((uintx)1, CMSIndexedFreeListReplenish);
   _promoInfo.setSpace(this);
@@ -297,22 +262,7 @@
   MemRegion mr(compaction_top(), end());
   reset(mr);
   // Now refill the linear allocation block(s) if possible.
-  if (_adaptive_freelists) {
-    refillLinearAllocBlocksIfNeeded();
-  } else {
-    // Place as much of mr in the linAB as we can get,
-    // provided it was big enough to go into the dictionary.
-    FreeChunk* fc = dictionary()->find_largest_dict();
-    if (fc != NULL) {
-      assert(fc->size() == mr.word_size(),
-             "Why was the chunk broken up?");
-      removeChunkFromDictionary(fc);
-      HeapWord* addr = (HeapWord*) fc;
-      _smallLinearAllocBlock.set(addr, fc->size() ,
-        1024*SmallForLinearAlloc, fc->size());
-      // Note that _unallocated_block is not updated here.
-    }
-  }
+  refillLinearAllocBlocksIfNeeded();
 }
 
 // Walks the entire dictionary, returning a coterminal
@@ -445,8 +395,7 @@
 
   // dump_memory_block(_smallLinearAllocBlock->_ptr, 128);
 
-  st->print_cr(" _fitStrategy = %s, _adaptive_freelists = %s",
-               _fitStrategy?"true":"false", _adaptive_freelists?"true":"false");
+  st->print_cr(" _fitStrategy = %s", BOOL_TO_STR(_fitStrategy));
 }
 
 void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st)
@@ -617,23 +566,9 @@
       // Now, take this new chunk and add it to the free blocks.
       // Note that the BOT has not yet been updated for this block.
       size_t newFcSize = pointer_delta(value, prevEnd);
-      // XXX This is REALLY UGLY and should be fixed up. XXX
-      if (!_adaptive_freelists && _smallLinearAllocBlock._ptr == NULL) {
-        // Mark the boundary of the new block in BOT
-        _bt.mark_block(prevEnd, value);
-        // put it all in the linAB
-        MutexLockerEx x(parDictionaryAllocLock(),
-                        Mutex::_no_safepoint_check_flag);
-        _smallLinearAllocBlock._ptr = prevEnd;
-        _smallLinearAllocBlock._word_size = newFcSize;
-        repairLinearAllocBlock(&_smallLinearAllocBlock);
-        // Births of chunks put into a LinAB are not recorded.  Births
-        // of chunks as they are allocated out of a LinAB are.
-      } else {
-        // Add the block to the free lists, if possible coalescing it
-        // with the last free block, and update the BOT and census data.
-        addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize);
-      }
+      // Add the block to the free lists, if possible coalescing it
+      // with the last free block, and update the BOT and census data.
+      addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize);
     }
   }
 }
@@ -1177,11 +1112,7 @@
   assert(size == adjustObjectSize(size),
          "use adjustObjectSize() before calling into allocate()");
 
-  if (_adaptive_freelists) {
-    res = allocate_adaptive_freelists(size);
-  } else {  // non-adaptive free lists
-    res = allocate_non_adaptive_freelists(size);
-  }
+  res = allocate_adaptive_freelists(size);
 
   if (res != NULL) {
     // check that res does lie in this space!
@@ -1203,27 +1134,6 @@
   return res;
 }
 
-HeapWord* CompactibleFreeListSpace::allocate_non_adaptive_freelists(size_t size) {
-  HeapWord* res = NULL;
-  // try and use linear allocation for smaller blocks
-  if (size < _smallLinearAllocBlock._allocation_size_limit) {
-    // if successful, the following also adjusts block offset table
-    res = getChunkFromSmallLinearAllocBlock(size);
-  }
-  // Else triage to indexed lists for smaller sizes
-  if (res == NULL) {
-    if (size < SmallForDictionary) {
-      res = (HeapWord*) getChunkFromIndexedFreeList(size);
-    } else {
-      // else get it from the big dictionary; if even this doesn't
-      // work we are out of luck.
-      res = (HeapWord*)getChunkFromDictionaryExact(size);
-    }
-  }
-
-  return res;
-}
-
 HeapWord* CompactibleFreeListSpace::allocate_adaptive_freelists(size_t size) {
   assert_lock_strong(freelistLock());
   HeapWord* res = NULL;
@@ -1281,9 +1191,6 @@
   // bigLAB or a smallLAB plus refilling a PromotionInfo object.  MinChunkSize
   // is added because the dictionary may over-allocate to avoid fragmentation.
   size_t space = obj_size;
-  if (!_adaptive_freelists) {
-    space = MAX2(space, _smallLinearAllocBlock._refillSize);
-  }
   space += _promoInfo.refillSize() + 2 * MinChunkSize;
   return space;
 }
@@ -1698,11 +1605,7 @@
   size_t size = fc->size();
   _bt.verify_single_block((HeapWord*) fc, size);
   _bt.verify_not_unallocated((HeapWord*) fc, size);
-  if (_adaptive_freelists) {
-    _indexedFreeList[size].return_chunk_at_tail(fc);
-  } else {
-    _indexedFreeList[size].return_chunk_at_head(fc);
-  }
+  _indexedFreeList[size].return_chunk_at_tail(fc);
 #ifndef PRODUCT
   if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
      _indexedFreeList[size].verify_stats();
@@ -1931,10 +1834,6 @@
 void
 CompactibleFreeListSpace::gc_epilogue() {
   assert_locked();
-  if (PrintGCDetails && Verbose && !_adaptive_freelists) {
-    if (_smallLinearAllocBlock._word_size == 0)
-      warning("CompactibleFreeListSpace(epilogue):: Linear allocation failure");
-  }
   assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");
   _promoInfo.stopTrackingPromotions();
   repairLinearAllocationBlocks();
@@ -2060,13 +1959,6 @@
   }
 }
 
-// Support for concurrent collection policy decisions.
-bool CompactibleFreeListSpace::should_concurrent_collect() const {
-  // In the future we might want to add in fragmentation stats --
-  // including erosion of the "mountain" into this decision as well.
-  return !adaptive_freelists() && linearAllocationWouldFail();
-}
-
 // Support for compaction
 void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
   scan_and_forward(this, cp);
--- a/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/cms/compactibleFreeListSpace.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -138,15 +138,13 @@
   // Linear allocation blocks
   LinearAllocBlock _smallLinearAllocBlock;
 
-  FreeBlockDictionary<FreeChunk>::DictionaryChoice _dictionaryChoice;
   AFLBinaryTreeDictionary* _dictionary;    // Pointer to dictionary for large size blocks
 
   // Indexed array for small size blocks
   AdaptiveFreeList<FreeChunk> _indexedFreeList[IndexSetSize];
 
   // Allocation strategy
-  bool       _fitStrategy;        // Use best fit strategy
-  bool       _adaptive_freelists; // Use adaptive freelists
+  bool _fitStrategy;  // Use best fit strategy
 
   // This is an address close to the largest free chunk in the heap.
   // It is currently assumed to be at the end of the heap.  Free
@@ -204,10 +202,6 @@
   // strategy that attempts to keep the needed number of chunks in each
   // indexed free lists.
   HeapWord* allocate_adaptive_freelists(size_t size);
-  // Allocate from the linear allocation buffers first.  This allocation
-  // strategy assumes maximal coalescing can maintain chunks large enough
-  // to be used as linear allocation buffers.
-  HeapWord* allocate_non_adaptive_freelists(size_t size);
 
   // Gets a chunk from the linear allocation block (LinAB).  If there
   // is not enough space in the LinAB, refills it.
@@ -333,9 +327,7 @@
 
  public:
   // Constructor
-  CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr,
-                           bool use_adaptive_freelists,
-                           FreeBlockDictionary<FreeChunk>::DictionaryChoice);
+  CompactibleFreeListSpace(BlockOffsetSharedArray* bs, MemRegion mr);
   // Accessors
   bool bestFitFirst() { return _fitStrategy == FreeBlockBestFitFirst; }
   FreeBlockDictionary<FreeChunk>* dictionary() const { return _dictionary; }
@@ -349,8 +341,6 @@
   // chunk exists, return NULL.
   FreeChunk* find_chunk_at_end();
 
-  bool adaptive_freelists() const { return _adaptive_freelists; }
-
   void set_collector(CMSCollector* collector) { _collector = collector; }
 
   // Support for parallelization of rescan and marking.
@@ -536,9 +526,6 @@
   void      addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size,
               bool coalesced);
 
-  // Support for decisions regarding concurrent collection policy.
-  bool should_concurrent_collect() const;
-
   // Support for compaction.
   void prepare_for_compaction(CompactPoint* cp);
   void adjust_pointers();
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -190,9 +190,7 @@
 };
 
 ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
-     ReservedSpace rs, size_t initial_byte_size,
-     CardTableRS* ct, bool use_adaptive_freelists,
-     FreeBlockDictionary<FreeChunk>::DictionaryChoice dictionaryChoice) :
+     ReservedSpace rs, size_t initial_byte_size, CardTableRS* ct) :
   CardGeneration(rs, initial_byte_size, ct),
   _dilatation_factor(((double)MinChunkSize)/((double)(CollectedHeap::min_fill_size()))),
   _did_compact(false)
@@ -208,9 +206,7 @@
     _numWordsAllocated = 0;
   )
 
-  _cmsSpace = new CompactibleFreeListSpace(_bts, MemRegion(bottom, end),
-                                           use_adaptive_freelists,
-                                           dictionaryChoice);
+  _cmsSpace = new CompactibleFreeListSpace(_bts, MemRegion(bottom, end));
   NOT_PRODUCT(debug_cms_space = _cmsSpace;)
   _cmsSpace->_old_gen = this;
 
@@ -1312,13 +1308,6 @@
     }
     return true;
   }
-  if (_cmsSpace->should_concurrent_collect()) {
-    if (PrintGCDetails && Verbose) {
-      gclog_or_tty->print(" %s: collect because cmsSpace says so ",
-        short_name());
-    }
-    return true;
-  }
   return false;
 }
 
@@ -1766,9 +1755,8 @@
     MutexLockerEx hl(Heap_lock, safepoint_check);
     FreelistLocker fll(this);
     MutexLockerEx x(CGC_lock, safepoint_check);
-    if (_foregroundGCIsActive || !UseAsyncConcMarkSweepGC) {
-      // The foreground collector is active or we're
-      // not using asynchronous collections.  Skip this
+    if (_foregroundGCIsActive) {
+      // The foreground collector is. Skip this
       // background collection.
       assert(!_foregroundGCShouldWait, "Should be clear");
       return;
@@ -1795,7 +1783,7 @@
   }
 
   // Used for PrintGC
-  size_t prev_used;
+  size_t prev_used = 0;
   if (PrintGC && Verbose) {
     prev_used = _cmsGen->used();
   }
@@ -5214,9 +5202,8 @@
 
   verify_work_stacks_empty();
   // Restore evacuated mark words, if any, used for overflow list links
-  if (!CMSOverflowEarlyRestoration) {
-    restore_preserved_marks_if_any();
-  }
+  restore_preserved_marks_if_any();
+
   verify_overflow_empty();
 }
 
@@ -6186,17 +6173,8 @@
     assert(_mark_stack->isEmpty(), "post-condition (eager drainage)");
     assert(_collector->overflow_list_is_empty(),
            "overflow list was drained above");
-    // We could restore evacuated mark words, if any, used for
-    // overflow list links here because the overflow list is
-    // provably empty here. That would reduce the maximum
-    // size requirements for preserved_{oop,mark}_stack.
-    // But we'll just postpone it until we are all done
-    // so we can just stream through.
-    if (!_concurrent_precleaning && CMSOverflowEarlyRestoration) {
-      _collector->restore_preserved_marks_if_any();
-      assert(_collector->no_preserved_marks(), "No preserved marks");
-    }
-    assert(!CMSOverflowEarlyRestoration || _collector->no_preserved_marks(),
+
+    assert(_collector->no_preserved_marks(),
            "All preserved marks should have been restored above");
   }
 }
@@ -7372,14 +7350,6 @@
 
   set_freeFinger(freeFinger);
   set_freeRangeInFreeLists(freeRangeInFreeLists);
-  if (CMSTestInFreeList) {
-    if (freeRangeInFreeLists) {
-      FreeChunk* fc = (FreeChunk*) freeFinger;
-      assert(fc->is_free(), "A chunk on the free list should be free.");
-      assert(fc->size() > 0, "Free range should have a size");
-      assert(_sp->verify_chunk_in_free_list(fc), "Chunk is not in free lists");
-    }
-  }
 }
 
 // Note that the sweeper runs concurrently with mutators. Thus,
@@ -7532,12 +7502,7 @@
 
 void SweepClosure::do_already_free_chunk(FreeChunk* fc) {
   const size_t size = fc->size();
-  // Chunks that cannot be coalesced are not in the
-  // free lists.
-  if (CMSTestInFreeList && !fc->cantCoalesce()) {
-    assert(_sp->verify_chunk_in_free_list(fc),
-      "free chunk should be in free lists");
-  }
+
   // a chunk that is already free, should not have been
   // marked in the bit map
   HeapWord* const addr = (HeapWord*) fc;
@@ -7550,57 +7515,8 @@
   // See the definition of cantCoalesce().
   if (!fc->cantCoalesce()) {
     // This chunk can potentially be coalesced.
-    if (_sp->adaptive_freelists()) {
-      // All the work is done in
-      do_post_free_or_garbage_chunk(fc, size);
-    } else {  // Not adaptive free lists
-      // this is a free chunk that can potentially be coalesced by the sweeper;
-      if (!inFreeRange()) {
-        // if the next chunk is a free block that can't be coalesced
-        // it doesn't make sense to remove this chunk from the free lists
-        FreeChunk* nextChunk = (FreeChunk*)(addr + size);
-        assert((HeapWord*)nextChunk <= _sp->end(), "Chunk size out of bounds?");
-        if ((HeapWord*)nextChunk < _sp->end() &&     // There is another free chunk to the right ...
-            nextChunk->is_free()               &&     // ... which is free...
-            nextChunk->cantCoalesce()) {             // ... but can't be coalesced
-          // nothing to do
-        } else {
-          // Potentially the start of a new free range:
-          // Don't eagerly remove it from the free lists.
-          // No need to remove it if it will just be put
-          // back again.  (Also from a pragmatic point of view
-          // if it is a free block in a region that is beyond
-          // any allocated blocks, an assertion will fail)
-          // Remember the start of a free run.
-          initialize_free_range(addr, true);
-          // end - can coalesce with next chunk
-        }
-      } else {
-        // the midst of a free range, we are coalescing
-        print_free_block_coalesced(fc);
-        if (CMSTraceSweeper) {
-          gclog_or_tty->print("  -- pick up free block " PTR_FORMAT " (" SIZE_FORMAT ")\n", p2i(fc), size);
-        }
-        // remove it from the free lists
-        _sp->removeFreeChunkFromFreeLists(fc);
-        set_lastFreeRangeCoalesced(true);
-        // If the chunk is being coalesced and the current free range is
-        // in the free lists, remove the current free range so that it
-        // will be returned to the free lists in its entirety - all
-        // the coalesced pieces included.
-        if (freeRangeInFreeLists()) {
-          FreeChunk* ffc = (FreeChunk*) freeFinger();
-          assert(ffc->size() == pointer_delta(addr, freeFinger()),
-            "Size of free range is inconsistent with chunk size.");
-          if (CMSTestInFreeList) {
-            assert(_sp->verify_chunk_in_free_list(ffc),
-              "free range is not in free lists");
-          }
-          _sp->removeFreeChunkFromFreeLists(ffc);
-          set_freeRangeInFreeLists(false);
-        }
-      }
-    }
+    // All the work is done in
+    do_post_free_or_garbage_chunk(fc, size);
     // Note that if the chunk is not coalescable (the else arm
     // below), we unconditionally flush, without needing to do
     // a "lookahead," as we do below.
@@ -7626,46 +7542,11 @@
   HeapWord* const addr = (HeapWord*) fc;
   const size_t size = CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size());
 
-  if (_sp->adaptive_freelists()) {
-    // Verify that the bit map has no bits marked between
-    // addr and purported end of just dead object.
-    _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
-
-    do_post_free_or_garbage_chunk(fc, size);
-  } else {
-    if (!inFreeRange()) {
-      // start of a new free range
-      assert(size > 0, "A free range should have a size");
-      initialize_free_range(addr, false);
-    } else {
-      // this will be swept up when we hit the end of the
-      // free range
-      if (CMSTraceSweeper) {
-        gclog_or_tty->print("  -- pick up garbage " PTR_FORMAT " (" SIZE_FORMAT ")\n", p2i(fc), size);
-      }
-      // If the chunk is being coalesced and the current free range is
-      // in the free lists, remove the current free range so that it
-      // will be returned to the free lists in its entirety - all
-      // the coalesced pieces included.
-      if (freeRangeInFreeLists()) {
-        FreeChunk* ffc = (FreeChunk*)freeFinger();
-        assert(ffc->size() == pointer_delta(addr, freeFinger()),
-          "Size of free range is inconsistent with chunk size.");
-        if (CMSTestInFreeList) {
-          assert(_sp->verify_chunk_in_free_list(ffc),
-            "free range is not in free lists");
-        }
-        _sp->removeFreeChunkFromFreeLists(ffc);
-        set_freeRangeInFreeLists(false);
-      }
-      set_lastFreeRangeCoalesced(true);
-    }
-    // this will be swept up when we hit the end of the free range
-
-    // Verify that the bit map has no bits marked between
-    // addr and purported end of just dead object.
-    _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
-  }
+  // Verify that the bit map has no bits marked between
+  // addr and purported end of just dead object.
+  _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
+  do_post_free_or_garbage_chunk(fc, size);
+
   assert(_limit >= addr + size,
          "A freshly garbage chunk can't possibly straddle over _limit");
   if (inFreeRange()) lookahead_and_flush(fc, size);
@@ -7727,11 +7608,7 @@
   // do_post_free_or_garbage_chunk() should only be called in the case
   // of the adaptive free list allocator.
   const bool fcInFreeLists = fc->is_free();
-  assert(_sp->adaptive_freelists(), "Should only be used in this case.");
   assert((HeapWord*)fc <= _limit, "sweep invariant");
-  if (CMSTestInFreeList && fcInFreeLists) {
-    assert(_sp->verify_chunk_in_free_list(fc), "free chunk is not in free lists");
-  }
 
   if (CMSTraceSweeper) {
     gclog_or_tty->print_cr("  -- pick up another chunk at " PTR_FORMAT " (" SIZE_FORMAT ")", p2i(fc), chunkSize);
@@ -7739,7 +7616,7 @@
 
   HeapWord* const fc_addr = (HeapWord*) fc;
 
-  bool coalesce;
+  bool coalesce = false;
   const size_t left  = pointer_delta(fc_addr, freeFinger());
   const size_t right = chunkSize;
   switch (FLSCoalescePolicy) {
@@ -7784,10 +7661,6 @@
       FreeChunk* const ffc = (FreeChunk*)freeFinger();
       assert(ffc->size() == pointer_delta(fc_addr, freeFinger()),
         "Size of free range is inconsistent with chunk size.");
-      if (CMSTestInFreeList) {
-        assert(_sp->verify_chunk_in_free_list(ffc),
-          "Chunk is not in free lists");
-      }
       _sp->coalDeath(ffc->size());
       _sp->removeFreeChunkFromFreeLists(ffc);
       set_freeRangeInFreeLists(false);
@@ -7856,12 +7729,6 @@
   assert(size > 0,
     "A zero sized chunk cannot be added to the free lists.");
   if (!freeRangeInFreeLists()) {
-    if (CMSTestInFreeList) {
-      FreeChunk* fc = (FreeChunk*) chunk;
-      fc->set_size(size);
-      assert(!_sp->verify_chunk_in_free_list(fc),
-        "chunk should not be in free lists yet");
-    }
     if (CMSTraceSweeper) {
       gclog_or_tty->print_cr(" -- add free block " PTR_FORMAT " (" SIZE_FORMAT ") to free lists",
                     p2i(chunk), size);
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1076,10 +1076,7 @@
   void assert_correct_size_change_locking();
 
  public:
-  ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
-                                CardTableRS* ct,
-                                bool use_adaptive_freelists,
-                                FreeBlockDictionary<FreeChunk>::DictionaryChoice);
+  ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, CardTableRS* ct);
 
   // Accessors
   CMSCollector* collector() const { return _collector; }
@@ -1121,12 +1118,6 @@
   // over-rides
   MemRegion used_region_at_save_marks() const;
 
-  // Does a "full" (forced) collection invoked on this generation collect
-  // the young generation as well?
-  virtual bool full_collects_young_generation() const {
-    return !ScavengeBeforeFullGC;
-  }
-
   // Adjust quantities in the generation affected by
   // the compaction.
   void reset_after_compaction();
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -79,9 +79,6 @@
   static void makeSurrogateLockerThread(TRAPS);
   static SurrogateLockerThread* slt() { return _slt; }
 
-  // Tester
-  bool is_ConcurrentGC_thread() const { return true;       }
-
   static void threads_do(ThreadClosure* tc);
 
   // Printing
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -138,7 +138,6 @@
     : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */)
   {
     assert(FullGCCount_lock != NULL, "Error");
-    assert(UseAsyncConcMarkSweepGC, "Else will hang caller");
   }
   ~VM_GenCollectFullConcurrent() {}
   virtual VMOp_Type type() const { return VMOp_GenCollectFullConcurrent; }
--- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -30,7 +30,8 @@
 #include "runtime/java.hpp"
 
 ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) :
-  _threads(NULL), _n_threads(0),
+  _threads(NULL),
+  _sample_thread(NULL),
   _hot_card_cache(g1h)
 {
   // Ergonomically select initial concurrent refinement parameters
@@ -58,12 +59,10 @@
     return NULL;
   }
   cg1r->_n_worker_threads = thread_num();
-  // We need one extra thread to do the young gen rset size sampling.
-  cg1r->_n_threads = cg1r->_n_worker_threads + 1;
 
   cg1r->reset_threshold_step();
 
-  cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_threads, mtGC);
+  cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_worker_threads, mtGC);
   if (cg1r->_threads == NULL) {
     *ecode = JNI_ENOMEM;
     vm_shutdown_during_initialization("Could not allocate an array for ConcurrentG1RefineThread");
@@ -73,7 +72,7 @@
   uint worker_id_offset = DirtyCardQueueSet::num_par_ids();
 
   ConcurrentG1RefineThread *next = NULL;
-  for (uint i = cg1r->_n_threads - 1; i != UINT_MAX; i--) {
+  for (uint i = cg1r->_n_worker_threads - 1; i != UINT_MAX; i--) {
     ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(cg1r, next, refine_closure, worker_id_offset, i);
     assert(t != NULL, "Conc refine should have been created");
     if (t->osthread() == NULL) {
@@ -86,6 +85,14 @@
     cg1r->_threads[i] = t;
     next = t;
   }
+
+  cg1r->_sample_thread = new G1YoungRemSetSamplingThread();
+  if (cg1r->_sample_thread->osthread() == NULL) {
+    *ecode = JNI_ENOMEM;
+    vm_shutdown_during_initialization("Could not create G1YoungRemSetSamplingThread");
+    return NULL;
+  }
+
   *ecode = JNI_OK;
   return cg1r;
 }
@@ -103,44 +110,36 @@
 }
 
 void ConcurrentG1Refine::stop() {
-  if (_threads != NULL) {
-    for (uint i = 0; i < _n_threads; i++) {
-      _threads[i]->stop();
-    }
+  for (uint i = 0; i < _n_worker_threads; i++) {
+    _threads[i]->stop();
   }
+  _sample_thread->stop();
 }
 
 void ConcurrentG1Refine::reinitialize_threads() {
   reset_threshold_step();
-  if (_threads != NULL) {
-    for (uint i = 0; i < _n_threads; i++) {
-      _threads[i]->initialize();
-    }
+  for (uint i = 0; i < _n_worker_threads; i++) {
+    _threads[i]->initialize();
   }
 }
 
 ConcurrentG1Refine::~ConcurrentG1Refine() {
-  if (_threads != NULL) {
-    for (uint i = 0; i < _n_threads; i++) {
-      delete _threads[i];
-    }
-    FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads);
+  for (uint i = 0; i < _n_worker_threads; i++) {
+    delete _threads[i];
   }
+  FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads);
+
+  delete _sample_thread;
 }
 
 void ConcurrentG1Refine::threads_do(ThreadClosure *tc) {
-  if (_threads != NULL) {
-    for (uint i = 0; i < _n_threads; i++) {
-      tc->do_thread(_threads[i]);
-    }
-  }
+  worker_threads_do(tc);
+  tc->do_thread(_sample_thread);
 }
 
 void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) {
-  if (_threads != NULL) {
-    for (uint i = 0; i < worker_thread_num(); i++) {
-      tc->do_thread(_threads[i]);
-    }
+  for (uint i = 0; i < worker_thread_num(); i++) {
+    tc->do_thread(_threads[i]);
   }
 }
 
@@ -149,12 +148,10 @@
 }
 
 void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const {
-  for (uint i = 0; i < _n_threads; ++i) {
+  for (uint i = 0; i < _n_worker_threads; ++i) {
     _threads[i]->print_on(st);
     st->cr();
   }
+  _sample_thread->print_on(st);
+  st->cr();
 }
-
-ConcurrentG1RefineThread * ConcurrentG1Refine::sampling_thread() const {
-  return _threads[worker_thread_num()];
-}
--- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_G1_CONCURRENTG1REFINE_HPP
 
 #include "gc/g1/g1HotCardCache.hpp"
+#include "gc/g1/g1YoungRemSetSamplingThread.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -39,8 +40,9 @@
 class DirtyCardQueue;
 
 class ConcurrentG1Refine: public CHeapObj<mtGC> {
+  G1YoungRemSetSamplingThread* _sample_thread;
+
   ConcurrentG1RefineThread** _threads;
-  uint _n_threads;
   uint _n_worker_threads;
  /*
   * The value of the update buffer queue length falls into one of 3 zones:
@@ -91,8 +93,8 @@
   // Iterate over all worker refinement threads
   void worker_threads_do(ThreadClosure * tc);
 
-  // The RS sampling thread
-  ConcurrentG1RefineThread * sampling_thread() const;
+  // The RS sampling thread has nothing to do with refinement, but is here for now.
+  G1YoungRemSetSamplingThread * sampling_thread() const { return _sample_thread; }
 
   static uint thread_num();
 
@@ -106,7 +108,6 @@
   int yellow_zone() const     { return _yellow_zone; }
   int red_zone() const        { return _red_zone;    }
 
-  uint total_thread_num() const  { return _n_threads;        }
   uint worker_thread_num() const { return _n_worker_threads; }
 
   int thread_threshold_step() const { return _thread_threshold_step; }
--- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -50,9 +50,8 @@
   // Each thread has its own monitor. The i-th thread is responsible for signaling
   // to thread i+1 if the number of buffers in the queue exceeds a threshold for this
   // thread. Monitors are also used to wake up the threads during termination.
-  // The 0th worker in notified by mutator threads and has a special monitor.
-  // The last worker is used for young gen rset size sampling.
-  if (worker_id > 0) {
+  // The 0th (primary) worker is notified by mutator threads and has a special monitor.
+  if (!is_primary()) {
     _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true,
                            Monitor::_safepoint_check_never);
   } else {
@@ -66,61 +65,11 @@
 }
 
 void ConcurrentG1RefineThread::initialize() {
-  if (_worker_id < cg1r()->worker_thread_num()) {
-    // Current thread activation threshold
-    _threshold = MIN2<int>(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(),
-                           cg1r()->yellow_zone());
-    // A thread deactivates once the number of buffer reached a deactivation threshold
-    _deactivation_threshold = MAX2<int>(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone());
-  } else {
-    set_active(true);
-  }
-}
-
-void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
-  SuspendibleThreadSetJoiner sts_join;
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  G1CollectorPolicy* g1p = g1h->g1_policy();
-  if (g1p->adaptive_young_list_length()) {
-    int regions_visited = 0;
-    g1h->young_list()->rs_length_sampling_init();
-    while (g1h->young_list()->rs_length_sampling_more()) {
-      g1h->young_list()->rs_length_sampling_next();
-      ++regions_visited;
-
-      // we try to yield every time we visit 10 regions
-      if (regions_visited == 10) {
-        if (sts_join.should_yield()) {
-          sts_join.yield();
-          // we just abandon the iteration
-          break;
-        }
-        regions_visited = 0;
-      }
-    }
-
-    g1p->revise_young_list_target_length_if_necessary();
-  }
-}
-
-void ConcurrentG1RefineThread::run_young_rs_sampling() {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-  _vtime_start = os::elapsedVTime();
-  while(!_should_terminate) {
-    sample_young_list_rs_lengths();
-
-    if (os::supports_vtime()) {
-      _vtime_accum = (os::elapsedVTime() - _vtime_start);
-    } else {
-      _vtime_accum = 0.0;
-    }
-
-    MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
-    if (_should_terminate) {
-      break;
-    }
-    _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefinementServiceIntervalMillis);
-  }
+  // Current thread activation threshold
+  _threshold = MIN2<int>(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(),
+                         cg1r()->yellow_zone());
+  // A thread deactivates once the number of buffer reached a deactivation threshold
+  _deactivation_threshold = MAX2<int>(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone());
 }
 
 void ConcurrentG1RefineThread::wait_for_completed_buffers() {
@@ -133,12 +82,12 @@
 
 bool ConcurrentG1RefineThread::is_active() {
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-  return _worker_id > 0 ? _active : dcqs.process_completed_buffers();
+  return is_primary() ? dcqs.process_completed_buffers() : _active;
 }
 
 void ConcurrentG1RefineThread::activate() {
   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
-  if (_worker_id > 0) {
+  if (!is_primary()) {
     if (G1TraceConcRefinement) {
       DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
       gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d",
@@ -154,7 +103,7 @@
 
 void ConcurrentG1RefineThread::deactivate() {
   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
-  if (_worker_id > 0) {
+  if (!is_primary()) {
     if (G1TraceConcRefinement) {
       DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
       gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d",
@@ -171,25 +120,24 @@
   initialize_in_thread();
   wait_for_universe_init();
 
-  if (_worker_id >= cg1r()->worker_thread_num()) {
-    run_young_rs_sampling();
-    terminate();
-    return;
-  }
+  run_service();
+
+  terminate();
+}
 
+void ConcurrentG1RefineThread::run_service() {
   _vtime_start = os::elapsedVTime();
+
   while (!_should_terminate) {
-    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-
     // Wait for work
     wait_for_completed_buffers();
-
     if (_should_terminate) {
       break;
     }
 
     {
       SuspendibleThreadSetJoiner sts_join;
+      DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
 
       do {
         int curr_buffer_num = (int)dcqs.completed_buffers_num();
@@ -199,7 +147,7 @@
           dcqs.set_completed_queue_padding(0);
         }
 
-        if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
+        if (!is_primary() && curr_buffer_num <= _deactivation_threshold) {
           // If the number of the buffer has fallen below our threshold
           // we should deactivate. The predecessor will reactivate this
           // thread should the number of the buffers cross the threshold again.
@@ -225,8 +173,10 @@
       _vtime_accum = 0.0;
     }
   }
-  assert(_should_terminate, "just checking");
-  terminate();
+
+  if (G1TraceConcRefinement) {
+    gclog_or_tty->print_cr("G1-Refine-stop");
+  }
 }
 
 void ConcurrentG1RefineThread::stop() {
@@ -236,10 +186,7 @@
     _should_terminate = true;
   }
 
-  {
-    MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
-    _monitor->notify();
-  }
+  stop_service();
 
   {
     MutexLockerEx mu(Terminator_lock);
@@ -247,8 +194,9 @@
       Terminator_lock->wait();
     }
   }
-  if (G1TraceConcRefinement) {
-    gclog_or_tty->print_cr("G1-Refine-stop");
-  }
 }
 
+void ConcurrentG1RefineThread::stop_service() {
+  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  _monitor->notify();
+}
\ No newline at end of file
--- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -31,14 +31,14 @@
 class CardTableEntryClosure;
 class ConcurrentG1Refine;
 
-// The G1 Concurrent Refinement Thread (could be several in the future).
-
+// One or more G1 Concurrent Refinement Threads may be active if concurrent
+// refinement is in progress.
 class ConcurrentG1RefineThread: public ConcurrentGCThread {
   friend class VMStructs;
   friend class G1CollectedHeap;
 
   double _vtime_start;  // Initial virtual time.
-  double _vtime_accum;  // Initial virtual time.
+  double _vtime_accum;  // Accumulated virtual time.
   uint _worker_id;
   uint _worker_id_offset;
 
@@ -59,8 +59,6 @@
   // This thread deactivation threshold
   int _deactivation_threshold;
 
-  void sample_young_list_rs_lengths();
-  void run_young_rs_sampling();
   void wait_for_completed_buffers();
 
   void set_active(bool x) { _active = x; }
@@ -68,6 +66,11 @@
   void activate();
   void deactivate();
 
+  bool is_primary() { return (_worker_id == 0); }
+
+  void run_service();
+  void stop_service();
+
 public:
   virtual void run();
   // Constructor
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -92,15 +92,31 @@
   }
 }
 
+// Marking pauses can be scheduled flexibly, so we might delay marking to meet MMU.
+void ConcurrentMarkThread::delay_to_keep_mmu(G1CollectorPolicy* g1_policy, bool remark) {
+  if (g1_policy->adaptive_young_list_length()) {
+    double now = os::elapsedTime();
+    double prediction_ms = remark ? g1_policy->predict_remark_time_ms()
+                                  : g1_policy->predict_cleanup_time_ms();
+    G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
+    jlong sleep_time_ms = mmu_tracker->when_ms(now, prediction_ms);
+    os::sleep(this, sleep_time_ms, false);
+  }
+}
 void ConcurrentMarkThread::run() {
   initialize_in_thread();
+  wait_for_universe_init();
+
+  run_service();
+
+  terminate();
+}
+
+void ConcurrentMarkThread::run_service() {
   _vtime_start = os::elapsedVTime();
-  wait_for_universe_init();
 
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1CollectorPolicy* g1_policy = g1h->g1_policy();
-  G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
-  Thread *current_thread = Thread::current();
 
   while (!_should_terminate) {
     // wait until started is set.
@@ -141,12 +157,7 @@
         double mark_end_sec = os::elapsedTime();
         _vtime_mark_accum += (mark_end_time - cycle_start);
         if (!cm()->has_aborted()) {
-          if (g1_policy->adaptive_young_list_length()) {
-            double now = os::elapsedTime();
-            double remark_prediction_ms = g1_policy->predict_remark_time_ms();
-            jlong sleep_time_ms = mmu_tracker->when_ms(now, remark_prediction_ms);
-            os::sleep(current_thread, sleep_time_ms, false);
-          }
+          delay_to_keep_mmu(g1_policy, true /* remark */);
 
           cm_log(G1Log::fine(), true, "[GC concurrent-mark-end, %1.7lf secs]", mark_end_sec - mark_start_sec);
 
@@ -167,12 +178,7 @@
       _vtime_accum = (end_time - _vtime_start);
 
       if (!cm()->has_aborted()) {
-        if (g1_policy->adaptive_young_list_length()) {
-          double now = os::elapsedTime();
-          double cleanup_prediction_ms = g1_policy->predict_cleanup_time_ms();
-          jlong sleep_time_ms = mmu_tracker->when_ms(now, cleanup_prediction_ms);
-          os::sleep(current_thread, sleep_time_ms, false);
-        }
+        delay_to_keep_mmu(g1_policy, false /* cleanup */);
 
         CMCleanUp cl_cl(_cm);
         VM_CGC_Operation op(&cl_cl, "GC cleanup", false /* needs_pll */);
@@ -272,9 +278,6 @@
       g1h->register_concurrent_cycle_end();
     }
   }
-  assert(_should_terminate, "just checking");
-
-  terminate();
 }
 
 void ConcurrentMarkThread::stop() {
@@ -283,10 +286,7 @@
     _should_terminate = true;
   }
 
-  {
-    MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag);
-    CGC_lock->notify_all();
-  }
+  stop_service();
 
   {
     MutexLockerEx ml(Terminator_lock);
@@ -296,6 +296,11 @@
   }
 }
 
+void ConcurrentMarkThread::stop_service() {
+  MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag);
+  CGC_lock->notify_all();
+}
+
 void ConcurrentMarkThread::sleepBeforeNextCycle() {
   // We join here because we don't want to do the "shouldConcurrentMark()"
   // below while the world is otherwise stopped.
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -27,11 +27,11 @@
 
 #include "gc/shared/concurrentGCThread.hpp"
 
-// The Concurrent Mark GC Thread (could be several in the future).
-// This is copied from the Concurrent Mark Sweep GC Thread
-// Still under construction.
+// The Concurrent Mark GC Thread triggers the parallel CMConcurrentMarkingTasks
+// as well as handling various marking cleanup.
 
 class ConcurrentMark;
+class G1CollectorPolicy;
 
 class ConcurrentMarkThread: public ConcurrentGCThread {
   friend class VMStructs;
@@ -57,6 +57,10 @@
   volatile State _state;
 
   void sleepBeforeNextCycle();
+  void delay_to_keep_mmu(G1CollectorPolicy* g1_policy, bool remark);
+
+  void run_service();
+  void stop_service();
 
   static SurrogateLockerThread*         _slt;
 
@@ -67,9 +71,9 @@
   static void makeSurrogateLockerThread(TRAPS);
   static SurrogateLockerThread* slt() { return _slt; }
 
-  // Total virtual time so far.
+  // Total virtual time so far for this thread and concurrent marking tasks.
   double vtime_accum();
-  // Marking virtual time so far
+  // Marking virtual time so far this thread and concurrent marking tasks.
   double vtime_mark_accum();
 
   ConcurrentMark* cm()     { return _cm; }
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1716,7 +1716,7 @@
   return NULL;
 }
 
-bool G1CollectedHeap::expand(size_t expand_bytes) {
+bool G1CollectedHeap::expand(size_t expand_bytes, double* expand_time_ms) {
   size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
   aligned_expand_bytes = align_size_up(aligned_expand_bytes,
                                        HeapRegion::GrainBytes);
@@ -1733,10 +1733,14 @@
     return false;
   }
 
+  double expand_heap_start_time_sec = os::elapsedTime();
   uint regions_to_expand = (uint)(aligned_expand_bytes / HeapRegion::GrainBytes);
   assert(regions_to_expand > 0, "Must expand by at least one region");
 
   uint expanded_by = _hrm.expand_by(regions_to_expand);
+  if (expand_time_ms != NULL) {
+    *expand_time_ms = (os::elapsedTime() - expand_heap_start_time_sec) * MILLIUNITS;
+  }
 
   if (expanded_by > 0) {
     size_t actual_expand_bytes = expanded_by * HeapRegion::GrainBytes;
@@ -3930,9 +3934,13 @@
         _allocator->init_gc_alloc_regions(evacuation_info);
 
         G1ParScanThreadStateSet per_thread_states(this, workers()->active_workers(), g1_policy()->young_cset_region_length());
+        pre_evacuate_collection_set();
+
         // Actually do the work...
         evacuate_collection_set(evacuation_info, &per_thread_states);
 
+        post_evacuate_collection_set(evacuation_info, &per_thread_states);
+
         const size_t* surviving_young_words = per_thread_states.surviving_young_words();
         free_collection_set(g1_policy()->collection_set(), evacuation_info, surviving_young_words);
 
@@ -3997,9 +4005,11 @@
             size_t bytes_before = capacity();
             // No need for an ergo verbose message here,
             // expansion_amount() does this when it returns a value > 0.
-            if (!expand(expand_bytes)) {
+            double expand_ms;
+            if (!expand(expand_bytes, &expand_ms)) {
               // We failed to expand the heap. Cannot do anything about it.
             }
+            g1_policy()->phase_times()->record_expand_heap_time(expand_ms);
           }
         }
 
@@ -4584,20 +4594,16 @@
     Klass* klass;
     do {
       klass =_klass_iterator.next_klass();
-    } while (klass != NULL && !klass->oop_is_instance());
-
-    return (InstanceKlass*)klass;
+    } while (klass != NULL && !klass->is_instance_klass());
+
+    // this can be null so don't call InstanceKlass::cast
+    return static_cast<InstanceKlass*>(klass);
   }
 
 public:
 
   void clean_klass(InstanceKlass* ik) {
-    ik->clean_implementors_list(_is_alive);
-    ik->clean_method_data(_is_alive);
-
-    // G1 specific cleanup work that has
-    // been moved here to be done in parallel.
-    ik->clean_dependent_nmethods();
+    ik->clean_weak_instanceklass_links(_is_alive);
   }
 
   void work() {
@@ -5164,27 +5170,29 @@
   g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0);
 }
 
-void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
+void G1CollectedHeap::pre_evacuate_collection_set() {
   _expand_heap_after_alloc_failure = true;
   _evacuation_failed = false;
 
-  // Should G1EvacuationFailureALot be in effect for this GC?
-  NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();)
-
-  g1_rem_set()->prepare_for_oops_into_collection_set_do();
-
   // Disable the hot card cache.
   G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
   hot_card_cache->reset_hot_cache_claimed_index();
   hot_card_cache->set_use_cache(false);
 
-  const uint n_workers = workers()->active_workers();
+}
+
+void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
+  g1_rem_set()->prepare_for_oops_into_collection_set_do();
+
+  // Should G1EvacuationFailureALot be in effect for this GC?
+  NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();)
 
   assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
   double start_par_time_sec = os::elapsedTime();
   double end_par_time_sec;
 
   {
+    const uint n_workers = workers()->active_workers();
     G1RootProcessor root_processor(this, n_workers);
     G1ParTask g1_par_task(this, per_thread_states, _task_queues, &root_processor, n_workers);
     // InitialMark needs claim bits to keep track of the marked-through CLDs.
@@ -5234,21 +5242,8 @@
     phase_times->record_string_dedup_fixup_time(fixup_time_ms);
   }
 
-  _allocator->release_gc_alloc_regions(evacuation_info);
   g1_rem_set()->cleanup_after_oops_into_collection_set_do();
 
-  per_thread_states->flush();
-
-  record_obj_copy_mem_stats();
-
-  // Reset and re-enable the hot card cache.
-  // Note the counts for the cards in the regions in the
-  // collection set are reset when the collection set is freed.
-  hot_card_cache->reset_hot_cache();
-  hot_card_cache->set_use_cache(true);
-
-  purge_code_root_memory();
-
   if (evacuation_failed()) {
     remove_self_forwarding_pointers();
 
@@ -5266,6 +5261,23 @@
   // cards). We need these updates logged to update any
   // RSets.
   enqueue_discovered_references(per_thread_states);
+}
+
+void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
+  _allocator->release_gc_alloc_regions(evacuation_info);
+
+  per_thread_states->flush();
+
+  record_obj_copy_mem_stats();
+
+  // Reset and re-enable the hot card cache.
+  // Note the counts for the cards in the regions in the
+  // collection set are reset when the collection set is freed.
+  G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
+  hot_card_cache->reset_hot_cache();
+  hot_card_cache->set_use_cache(true);
+
+  purge_code_root_memory();
 
   redirty_logged_cards();
 #if defined(COMPILER2) || INCLUDE_JVMCI
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -538,7 +538,7 @@
   // Returns true if the heap was expanded by the requested amount;
   // false otherwise.
   // (Rounds up to a HeapRegion boundary.)
-  bool expand(size_t expand_bytes);
+  bool expand(size_t expand_bytes, double* expand_time_ms = NULL);
 
   // Returns the PLAB statistics for a given destination.
   inline G1EvacStats* alloc_buffer_stats(InCSetState dest);
@@ -728,7 +728,10 @@
   bool do_collection_pause_at_safepoint(double target_pause_time_ms);
 
   // Actually do the work of evacuating the collection set.
-  void evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states);
+  virtual void evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states);
+
+  void pre_evacuate_collection_set();
+  void post_evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
 
   // Print the header for the per-thread termination statistics.
   static void print_termination_stats_hdr(outputStream* const st);
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -431,7 +431,7 @@
   }
   _free_regions_at_end_of_collection = _g1->num_free_regions();
 
-  update_young_list_target_length();
+  update_young_list_max_and_target_length();
   // We may immediately start allocating regions and placing them on the
   // collection set list. Initialize the per-collection set info
   start_incremental_cset_building();
@@ -507,13 +507,24 @@
   return _young_gen_sizer->max_desired_young_length();
 }
 
+void G1CollectorPolicy::update_young_list_max_and_target_length() {
+  update_young_list_max_and_target_length(get_new_prediction(_rs_lengths_seq));
+}
+
+void G1CollectorPolicy::update_young_list_max_and_target_length(size_t rs_lengths) {
+  update_young_list_target_length(rs_lengths);
+  update_max_gc_locker_expansion();
+}
+
 void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) {
-  if (rs_lengths == (size_t) -1) {
-    // if it's set to the default value (-1), we should predict it;
-    // otherwise, use the given value.
-    rs_lengths = (size_t) get_new_prediction(_rs_lengths_seq);
-  }
+  _young_list_target_length = bounded_young_list_target_length(rs_lengths);
+}
 
+void G1CollectorPolicy::update_young_list_target_length() {
+  update_young_list_target_length(get_new_prediction(_rs_lengths_seq));
+}
+
+uint G1CollectorPolicy::bounded_young_list_target_length(size_t rs_lengths) const {
   // Calculate the absolute and desired min bounds.
 
   // This is how many young regions we already have (currently: the survivors).
@@ -544,7 +555,6 @@
                                                            base_min_length,
                                                            desired_min_length,
                                                            desired_max_length);
-      _rs_lengths_prediction = rs_lengths;
     } else {
       // Don't calculate anything and let the code below bound it to
       // the desired_min_length, i.e., do the next GC as soon as
@@ -569,9 +579,8 @@
   assert(young_list_target_length > recorded_survivor_regions(),
          "we should be able to allocate at least one eden region");
   assert(young_list_target_length >= absolute_min_length, "post-condition");
-  _young_list_target_length = young_list_target_length;
 
-  update_max_gc_locker_expansion();
+  return young_list_target_length;
 }
 
 uint
@@ -695,11 +704,21 @@
   if (rs_lengths > _rs_lengths_prediction) {
     // add 10% to avoid having to recalculate often
     size_t rs_lengths_prediction = rs_lengths * 1100 / 1000;
-    update_young_list_target_length(rs_lengths_prediction);
+    update_rs_lengths_prediction(rs_lengths_prediction);
+
+    update_young_list_max_and_target_length(rs_lengths_prediction);
   }
 }
 
+void G1CollectorPolicy::update_rs_lengths_prediction() {
+  update_rs_lengths_prediction(get_new_prediction(_rs_lengths_seq));
+}
 
+void G1CollectorPolicy::update_rs_lengths_prediction(size_t prediction) {
+  if (collector_state()->gcs_are_young() && adaptive_young_list_length()) {
+    _rs_lengths_prediction = prediction;
+  }
+}
 
 HeapWord* G1CollectorPolicy::mem_allocate_work(size_t size,
                                                bool is_tlab,
@@ -801,7 +820,8 @@
   _free_regions_at_end_of_collection = _g1->num_free_regions();
   // Reset survivors SurvRateGroup.
   _survivor_surv_rate_group->reset();
-  update_young_list_target_length();
+  update_young_list_max_and_target_length();
+  update_rs_lengths_prediction();
   _collectionSetChooser->clear();
 }
 
@@ -879,6 +899,10 @@
   }
 }
 
+double G1CollectorPolicy::average_time_ms(G1GCPhaseTimes::GCParPhases phase) const {
+  return phase_times()->average_time_ms(phase);
+}
+
 bool G1CollectorPolicy::need_to_start_conc_mark(const char* source, size_t alloc_word_size) {
   if (_g1->concurrent_mark()->cmThread()->during_cycle()) {
     return false;
@@ -1049,16 +1073,16 @@
 
   if (update_stats) {
     double cost_per_card_ms = 0.0;
-    double cost_scan_hcc = phase_times()->average_time_ms(G1GCPhaseTimes::ScanHCC);
+    double cost_scan_hcc = average_time_ms(G1GCPhaseTimes::ScanHCC);
     if (_pending_cards > 0) {
-      cost_per_card_ms = (phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) - cost_scan_hcc) / (double) _pending_cards;
+      cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - cost_scan_hcc) / (double) _pending_cards;
       _cost_per_card_ms_seq->add(cost_per_card_ms);
     }
     _cost_scan_hcc_seq->add(cost_scan_hcc);
 
     double cost_per_entry_ms = 0.0;
     if (cards_scanned > 10) {
-      cost_per_entry_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
+      cost_per_entry_ms = average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
       if (collector_state()->last_gc_was_young()) {
         _cost_per_entry_ms_seq->add(cost_per_entry_ms);
       } else {
@@ -1100,7 +1124,7 @@
     double cost_per_byte_ms = 0.0;
 
     if (copied_bytes > 0) {
-      cost_per_byte_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes;
+      cost_per_byte_ms = average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes;
       if (collector_state()->in_marking_window()) {
         _cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms);
       } else {
@@ -1109,8 +1133,8 @@
     }
 
     double all_other_time_ms = pause_time_ms -
-      (phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) + phase_times()->average_time_ms(G1GCPhaseTimes::ScanRS) +
-          phase_times()->average_time_ms(G1GCPhaseTimes::ObjCopy) + phase_times()->average_time_ms(G1GCPhaseTimes::Termination));
+      (average_time_ms(G1GCPhaseTimes::UpdateRS) + average_time_ms(G1GCPhaseTimes::ScanRS) +
+       average_time_ms(G1GCPhaseTimes::ObjCopy)  + average_time_ms(G1GCPhaseTimes::Termination));
 
     double young_other_time_ms = 0.0;
     if (young_cset_region_length() > 0) {
@@ -1147,12 +1171,13 @@
   collector_state()->set_in_marking_window(new_in_marking_window);
   collector_state()->set_in_marking_window_im(new_in_marking_window_im);
   _free_regions_at_end_of_collection = _g1->num_free_regions();
-  update_young_list_target_length();
+  update_young_list_max_and_target_length();
+  update_rs_lengths_prediction();
 
   // Note that _mmu_tracker->max_gc_time() returns the time in seconds.
   double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
 
-  double scan_hcc_time_ms = phase_times()->average_time_ms(G1GCPhaseTimes::ScanHCC);
+  double scan_hcc_time_ms = average_time_ms(G1GCPhaseTimes::ScanHCC);
 
   if (update_rs_time_goal_ms < scan_hcc_time_ms) {
     ergo_verbose2(ErgoTiming,
@@ -1167,7 +1192,7 @@
   } else {
     update_rs_time_goal_ms -= scan_hcc_time_ms;
   }
-  adjust_concurrent_refinement(phase_times()->average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
+  adjust_concurrent_refinement(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
                                phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
                                update_rs_time_goal_ms);
 
--- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -27,6 +27,7 @@
 
 #include "gc/g1/collectionSetChooser.hpp"
 #include "gc/g1/g1CollectorState.hpp"
+#include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1InCSetState.hpp"
 #include "gc/g1/g1MMUTracker.hpp"
 #include "gc/g1/g1Predictions.hpp"
@@ -39,7 +40,6 @@
 
 class HeapRegion;
 class CollectionSetChooser;
-class G1GCPhaseTimes;
 
 // TraceYoungGenTime collects data on _both_ young and mixed evacuation pauses
 // (the latter may contain non-young regions - i.e. regions that are
@@ -378,6 +378,9 @@
 
   double accum_yg_surv_rate_pred(int age) const;
 
+protected:
+  virtual double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const;
+
 private:
   // Statistics kept per GC stoppage, pause or full.
   TruncatedSeq* _recent_prev_end_times_for_all_gcs_sec;
@@ -465,12 +468,16 @@
   double _mark_remark_start_sec;
   double _mark_cleanup_start_sec;
 
+  void update_young_list_max_and_target_length();
+  void update_young_list_max_and_target_length(size_t rs_lengths);
+
   // Update the young list target length either by setting it to the
   // desired fixed value or by calculating it using G1's pause
   // prediction model. If no rs_lengths parameter is passed, predict
   // the RS lengths using the prediction model, otherwise use the
   // given rs_lengths as the prediction.
-  void update_young_list_target_length(size_t rs_lengths = (size_t) -1);
+  void update_young_list_target_length();
+  void update_young_list_target_length(size_t rs_lengths);
 
   // Calculate and return the minimum desired young list target
   // length. This is the minimum desired young list length according
@@ -493,6 +500,11 @@
                                           uint desired_min_length,
                                           uint desired_max_length) const;
 
+  uint bounded_young_list_target_length(size_t rs_lengths) const;
+
+  void update_rs_lengths_prediction();
+  void update_rs_lengths_prediction(size_t prediction);
+
   // Calculate and return chunk size (in number of regions) for parallel
   // concurrent mark cleanup.
   uint calculate_parallel_work_chunk_size(uint n_workers, uint n_regions) const;
--- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -104,9 +104,12 @@
     // Latch the result
     _desired_net_plab_sz = plab_sz;
     if (PrintPLAB) {
-      gclog_or_tty->print_cr(" (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ") ", cur_plab_sz, plab_sz);
+      gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ") ", cur_plab_sz, plab_sz);
     }
   }
+  if (PrintPLAB) {
+    gclog_or_tty->cr();
+  }
   // Clear accumulators for next round.
   reset();
 }
--- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -28,6 +28,7 @@
 #include "gc/g1/g1GCPhaseTimes.hpp"
 #include "gc/g1/g1Log.hpp"
 #include "gc/g1/g1StringDedup.hpp"
+#include "gc/g1/workerDataArray.inline.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/os.hpp"
 
@@ -86,165 +87,6 @@
   }
 };
 
-template <class T>
-class WorkerDataArray  : public CHeapObj<mtGC> {
-  friend class G1GCParPhasePrinter;
-  T*          _data;
-  uint        _length;
-  const char* _title;
-  bool        _print_sum;
-  int         _log_level;
-  uint        _indent_level;
-  bool        _enabled;
-
-  WorkerDataArray<size_t>* _thread_work_items;
-
-  NOT_PRODUCT(T uninitialized();)
-
-  // We are caching the sum and average to only have to calculate them once.
-  // This is not done in an MT-safe way. It is intended to allow single
-  // threaded code to call sum() and average() multiple times in any order
-  // without having to worry about the cost.
-  bool   _has_new_data;
-  T      _sum;
-  T      _min;
-  T      _max;
-  double _average;
-
- public:
-  WorkerDataArray(uint length, const char* title, bool print_sum, int log_level, uint indent_level) :
-    _title(title), _length(0), _print_sum(print_sum), _log_level(log_level), _indent_level(indent_level),
-    _has_new_data(true), _thread_work_items(NULL), _enabled(true) {
-    assert(length > 0, "Must have some workers to store data for");
-    _length = length;
-    _data = NEW_C_HEAP_ARRAY(T, _length, mtGC);
-  }
-
-  ~WorkerDataArray() {
-    FREE_C_HEAP_ARRAY(T, _data);
-  }
-
-  void link_thread_work_items(WorkerDataArray<size_t>* thread_work_items) {
-    _thread_work_items = thread_work_items;
-  }
-
-  WorkerDataArray<size_t>* thread_work_items() { return _thread_work_items; }
-
-  void set(uint worker_i, T value) {
-    assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
-    assert(_data[worker_i] == WorkerDataArray<T>::uninitialized(), "Overwriting data for worker %d in %s", worker_i, _title);
-    _data[worker_i] = value;
-    _has_new_data = true;
-  }
-
-  void set_thread_work_item(uint worker_i, size_t value) {
-    assert(_thread_work_items != NULL, "No sub count");
-    _thread_work_items->set(worker_i, value);
-  }
-
-  T get(uint worker_i) {
-    assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
-    assert(_data[worker_i] != WorkerDataArray<T>::uninitialized(), "No data added for worker %d", worker_i);
-    return _data[worker_i];
-  }
-
-  void add(uint worker_i, T value) {
-    assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
-    assert(_data[worker_i] != WorkerDataArray<T>::uninitialized(), "No data to add to for worker %d", worker_i);
-    _data[worker_i] += value;
-    _has_new_data = true;
-  }
-
-  double average(uint active_threads){
-    calculate_totals(active_threads);
-    return _average;
-  }
-
-  T sum(uint active_threads) {
-    calculate_totals(active_threads);
-    return _sum;
-  }
-
-  T minimum(uint active_threads) {
-    calculate_totals(active_threads);
-    return _min;
-  }
-
-  T maximum(uint active_threads) {
-    calculate_totals(active_threads);
-    return _max;
-  }
-
-  void reset() PRODUCT_RETURN;
-  void verify(uint active_threads) PRODUCT_RETURN;
-
-  void set_enabled(bool enabled) { _enabled = enabled; }
-
-  int log_level() { return _log_level;  }
-
- private:
-
-  void calculate_totals(uint active_threads){
-    if (!_has_new_data) {
-      return;
-    }
-
-    _sum = (T)0;
-    _min = _data[0];
-    _max = _min;
-    assert(active_threads <= _length, "Wrong number of active threads");
-    for (uint i = 0; i < active_threads; ++i) {
-      T val = _data[i];
-      _sum += val;
-      _min = MIN2(_min, val);
-      _max = MAX2(_max, val);
-    }
-    _average = (double)_sum / (double)active_threads;
-    _has_new_data = false;
-  }
-};
-
-
-#ifndef PRODUCT
-
-template <>
-size_t WorkerDataArray<size_t>::uninitialized() {
-  return (size_t)-1;
-}
-
-template <>
-double WorkerDataArray<double>::uninitialized() {
-  return -1.0;
-}
-
-template <class T>
-void WorkerDataArray<T>::reset() {
-  for (uint i = 0; i < _length; i++) {
-    _data[i] = WorkerDataArray<T>::uninitialized();
-  }
-  if (_thread_work_items != NULL) {
-    _thread_work_items->reset();
-  }
-}
-
-template <class T>
-void WorkerDataArray<T>::verify(uint active_threads) {
-  if (!_enabled) {
-    return;
-  }
-
-  assert(active_threads <= _length, "Wrong number of active threads");
-  for (uint i = 0; i < active_threads; i++) {
-    assert(_data[i] != WorkerDataArray<T>::uninitialized(),
-           "Invalid data for worker %u in '%s'", i, _title);
-  }
-  if (_thread_work_items != NULL) {
-    _thread_work_items->verify(active_threads);
-  }
-}
-
-#endif
-
 G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
   _max_gc_threads(max_gc_threads)
 {
@@ -298,6 +140,7 @@
   assert(active_gc_threads > 0, "The number of threads must be > 0");
   assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max number of threads");
   _active_gc_threads = active_gc_threads;
+  _cur_expand_heap_time_ms = 0.0;
 
   for (int i = 0; i < GCParPhasesSentinel; i++) {
     _gc_par_phases[i]->reset();
@@ -363,6 +206,9 @@
     // current value of "other time"
     misc_time_ms += _cur_clear_ct_time_ms;
 
+    // Remove expand heap time from "other time"
+    misc_time_ms += _cur_expand_heap_time_ms;
+
     return misc_time_ms;
 }
 
@@ -536,6 +382,8 @@
     }
   }
   print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
+  print_stats(1, "Expand Heap After Collection", _cur_expand_heap_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) {
--- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -92,6 +92,7 @@
   double _cur_string_dedup_fixup_time_ms;
 
   double _cur_clear_ct_time_ms;
+  double _cur_expand_heap_time_ms;
   double _cur_ref_proc_time_ms;
   double _cur_ref_enq_time_ms;
 
@@ -155,6 +156,10 @@
     _cur_clear_ct_time_ms = ms;
   }
 
+  void record_expand_heap_time(double ms) {
+    _cur_expand_heap_time_ms = ms;
+  }
+
   void record_par_time(double ms) {
     _cur_collection_par_time_ms = ms;
   }
@@ -252,6 +257,10 @@
     return _cur_clear_ct_time_ms;
   }
 
+  double cur_expand_heap_time_ms() {
+    return _cur_expand_heap_time_ms;
+  }
+
   double root_region_scan_wait_time_ms() {
     return _root_region_scan_wait_time_ms;
   }
--- a/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -29,11 +29,23 @@
 #include "memory/allocation.hpp"
 #include "utilities/debug.hpp"
 
-// Keeps track of the GC work and decides when it is OK to do GC work
+// Two major user controls over G1 behavior are setting a pause time goal (MaxGCPauseMillis),
+// over a time slice (GCPauseIntervalMillis). This defines the Minimum Mutator
+// Utilisation (MMU) goal.
+//
+// * Definitions *
+// Mutator Utilisation:
+// - for a given time slice duration "ts",
+// - mutator utilisation is the following fraction:
+//     non_gc_time / ts
+//
+// Minimum Mutator Utilisation (MMU):
+// - the worst mutator utilisation across all time slices.
+//
+// G1MMUTracker keeps track of the GC work and decides when it is OK to do GC work
 // and for how long so that the MMU invariants are maintained.
-
-/***** ALL TIMES ARE IN SECS!!!!!!! *****/
-
+//
+// ***** ALL TIMES ARE IN SECS!!!!!!! *****
 // this is the "interface"
 class G1MMUTracker: public CHeapObj<mtGC> {
 protected:
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -198,10 +198,11 @@
   _table = new G1StringDedupTable(_min_size);
 }
 
-void G1StringDedupTable::add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list) {
+void G1StringDedupTable::add(typeArrayOop value, bool latin1, unsigned int hash, G1StringDedupEntry** list) {
   G1StringDedupEntry* entry = _entry_cache->alloc();
   entry->set_obj(value);
   entry->set_hash(hash);
+  entry->set_latin1(latin1);
   entry->set_next(*list);
   *list = entry;
   _entries++;
@@ -226,15 +227,15 @@
 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)))));
+           (!memcmp(value1->base(T_BYTE),
+                    value2->base(T_BYTE),
+                    value1->length() * sizeof(jbyte)))));
 }
 
-typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, unsigned int hash,
+typeArrayOop G1StringDedupTable::lookup(typeArrayOop value, bool latin1, unsigned int hash,
                                         G1StringDedupEntry** list, uintx &count) {
   for (G1StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) {
-    if (entry->hash() == hash) {
+    if (entry->hash() == hash && entry->latin1() == latin1) {
       typeArrayOop existing_value = entry->obj();
       if (equals(value, existing_value)) {
         // Match found
@@ -248,13 +249,13 @@
   return NULL;
 }
 
-typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, unsigned int hash) {
+typeArrayOop G1StringDedupTable::lookup_or_add_inner(typeArrayOop value, bool latin1, 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);
+  typeArrayOop existing_value = lookup(value, latin1, hash, list, count);
 
   // Check if rehash is needed
   if (count > _rehash_threshold) {
@@ -263,7 +264,7 @@
 
   if (existing_value == NULL) {
     // Not found, add new entry
-    add(value, hash, list);
+    add(value, latin1, hash, list);
 
     // Update statistics
     _entries_added++;
@@ -272,15 +273,24 @@
   return existing_value;
 }
 
-unsigned int G1StringDedupTable::hash_code(typeArrayOop value) {
+unsigned int G1StringDedupTable::hash_code(typeArrayOop value, bool latin1) {
   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);
+  if (latin1) {
+    const jbyte* data = (jbyte*)value->base(T_BYTE);
+    if (use_java_hash()) {
+      hash = java_lang_String::hash_code(data, length);
+    } else {
+      hash = AltHashing::murmur3_32(_table->_hash_seed, data, length);
+    }
   } else {
-    hash = AltHashing::murmur3_32(_table->_hash_seed, data, length);
+    length /= sizeof(jchar) / sizeof(jbyte); // Convert number of bytes to number of chars
+    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;
@@ -299,6 +309,7 @@
     return;
   }
 
+  bool latin1 = java_lang_String::is_latin1(java_string);
   unsigned int hash = 0;
 
   if (use_java_hash()) {
@@ -308,7 +319,7 @@
 
   if (hash == 0) {
     // Compute hash
-    hash = hash_code(value);
+    hash = hash_code(value, latin1);
     stat.inc_hashed();
 
     if (use_java_hash() && hash != 0) {
@@ -317,7 +328,7 @@
     }
   }
 
-  typeArrayOop existing_value = lookup_or_add(value, hash);
+  typeArrayOop existing_value = lookup_or_add(value, latin1, hash);
   if (existing_value == value) {
     // Same value, already known
     stat.inc_known();
@@ -459,7 +470,8 @@
             // destination partitions. finish_rehash() will do a single
             // threaded transfer of all entries.
             typeArrayOop value = (typeArrayOop)*p;
-            unsigned int hash = hash_code(value);
+            bool latin1 = (*entry)->latin1();
+            unsigned int hash = hash_code(value, latin1);
             (*entry)->set_hash(hash);
           }
 
@@ -523,7 +535,8 @@
       guarantee(G1CollectedHeap::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);
+      bool latin1 = (*entry)->latin1();
+      unsigned int hash = hash_code(value, latin1);
       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();
@@ -536,10 +549,12 @@
     G1StringDedupEntry** entry1 = _table->bucket(bucket);
     while (*entry1 != NULL) {
       typeArrayOop value1 = (*entry1)->obj();
+      bool latin1_1 = (*entry1)->latin1();
       G1StringDedupEntry** entry2 = (*entry1)->next_addr();
       while (*entry2 != NULL) {
         typeArrayOop value2 = (*entry2)->obj();
-        guarantee(!equals(value1, value2), "Table entries must not have identical arrays");
+        bool latin1_2 = (*entry2)->latin1();
+        guarantee(latin1_1 != latin1_2 || !equals(value1, value2), "Table entries must not have identical arrays");
         entry2 = (*entry2)->next_addr();
       }
       entry1 = (*entry1)->next_addr();
--- a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -40,12 +40,14 @@
 private:
   G1StringDedupEntry* _next;
   unsigned int      _hash;
+  bool              _latin1;
   typeArrayOop      _obj;
 
 public:
   G1StringDedupEntry() :
     _next(NULL),
     _hash(0),
+    _latin1(false),
     _obj(NULL) {
   }
 
@@ -69,6 +71,14 @@
     _hash = hash;
   }
 
+  bool latin1() {
+    return _latin1;
+  }
+
+  void set_latin1(bool latin1) {
+    _latin1 = latin1;
+  }
+
   typeArrayOop obj() {
     return _obj;
   }
@@ -152,7 +162,7 @@
   }
 
   // Adds a new table entry to the given hash bucket.
-  void add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list);
+  void add(typeArrayOop value, bool latin1, unsigned int hash, G1StringDedupEntry** list);
 
   // Removes the given table entry from the table.
   void remove(G1StringDedupEntry** pentry, uint worker_id);
@@ -162,20 +172,20 @@
 
   // 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,
+  typeArrayOop lookup(typeArrayOop value, bool latin1, 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);
+  typeArrayOop lookup_or_add_inner(typeArrayOop value, bool latin1, unsigned int hash);
 
   // Thread safe lookup or add of table entry
-  static typeArrayOop lookup_or_add(typeArrayOop value, unsigned int hash) {
+  static typeArrayOop lookup_or_add(typeArrayOop value, bool latin1, 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);
+    return _table->lookup_or_add_inner(value, latin1, hash);
   }
 
   // Returns true if the hashtable is currently using a Java compatible
@@ -188,7 +198,7 @@
 
   // 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 unsigned int hash_code(typeArrayOop value, bool latin1);
 
   static uintx unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* cl,
                                  size_t partition_begin,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1CollectorPolicy.hpp"
+#include "gc/g1/g1YoungRemSetSamplingThread.hpp"
+#include "gc/g1/suspendibleThreadSet.hpp"
+#include "runtime/mutexLocker.hpp"
+
+void G1YoungRemSetSamplingThread::run() {
+  initialize_in_thread();
+  wait_for_universe_init();
+
+  run_service();
+
+  terminate();
+}
+
+void G1YoungRemSetSamplingThread::stop() {
+  // it is ok to take late safepoints here, if needed
+  {
+    MutexLockerEx mu(Terminator_lock);
+    _should_terminate = true;
+  }
+
+  stop_service();
+
+  {
+    MutexLockerEx mu(Terminator_lock);
+    while (!_has_terminated) {
+      Terminator_lock->wait();
+    }
+  }
+}
+
+G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : ConcurrentGCThread() {
+  _monitor = new Monitor(Mutex::nonleaf,
+                         "G1YoungRemSetSamplingThread monitor",
+                         true,
+                         Monitor::_safepoint_check_never);
+
+  create_and_start();
+
+  set_name("G1 Young RemSet Sampling");
+}
+
+void G1YoungRemSetSamplingThread::sleep_before_next_cycle() {
+  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  if (!_should_terminate) {
+    intx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be?
+    _monitor->wait(Mutex::_no_safepoint_check_flag, waitms);
+  }
+}
+
+void G1YoungRemSetSamplingThread::run_service() {
+  double vtime_start = os::elapsedVTime();
+
+  while (!_should_terminate) {
+    sample_young_list_rs_lengths();
+
+    if (os::supports_vtime()) {
+      _vtime_accum = (os::elapsedVTime() - vtime_start);
+    } else {
+      _vtime_accum = 0.0;
+    }
+
+    sleep_before_next_cycle();
+  }
+}
+
+void G1YoungRemSetSamplingThread::stop_service() {
+  MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+  _monitor->notify();
+}
+
+void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() {
+  SuspendibleThreadSetJoiner sts;
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  G1CollectorPolicy* g1p = g1h->g1_policy();
+  if (g1p->adaptive_young_list_length()) {
+    int regions_visited = 0;
+    g1h->young_list()->rs_length_sampling_init();
+    while (g1h->young_list()->rs_length_sampling_more()) {
+      g1h->young_list()->rs_length_sampling_next();
+      ++regions_visited;
+
+      // we try to yield every time we visit 10 regions
+      if (regions_visited == 10) {
+        if (sts.should_yield()) {
+          sts.yield();
+          // we just abandon the iteration
+          break;
+        }
+        regions_visited = 0;
+      }
+    }
+
+    g1p->revise_young_list_target_length_if_necessary();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP
+#define SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP
+
+#include "gc/shared/concurrentGCThread.hpp"
+
+// The G1YoungRemSetSamplingThread is used to re-assess the validity of
+// the prediction for the remembered set lengths of the young generation.
+//
+// At the end of the GC G1 determines the length of the young gen based on
+// how much time the next GC can take, and when the next GC may occur
+// according to the MMU.
+//
+// The assumption is that a significant part of the GC is spent on scanning
+// the remembered sets (and many other components), so this thread constantly
+// reevaluates the prediction for the remembered set scanning costs, and potentially
+// G1CollectorPolicy resizes the young gen. This may do a premature GC or even
+// increase the young gen size to keep pause time length goal.
+class G1YoungRemSetSamplingThread: public ConcurrentGCThread {
+private:
+  Monitor* _monitor;
+
+  void sample_young_list_rs_lengths();
+
+  void run_service();
+  void stop_service();
+
+  void sleep_before_next_cycle();
+
+  double _vtime_accum;  // Accumulated virtual time.
+
+public:
+  G1YoungRemSetSamplingThread();
+  double vtime_accum() { return _vtime_accum; }
+
+  virtual void run();
+  void stop();
+};
+
+#endif /* SHARE_VM_GC_G1_G1YOUNGREMSETSAMPLINGTHREAD_HPP */
--- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -660,7 +660,7 @@
   void print_object(outputStream* out, oop obj) {
 #ifdef PRODUCT
     Klass* k = obj->klass();
-    const char* class_name = InstanceKlass::cast(k)->external_name();
+    const char* class_name = k->external_name();
     out->print_cr("class name %s", class_name);
 #else // PRODUCT
     obj->print_on(out);
--- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -563,7 +563,7 @@
   assert(_n_fine_entries == _max_fine_entries, "Precondition");
   PerRegionTable* max = NULL;
   jint max_occ = 0;
-  PerRegionTable** max_prev;
+  PerRegionTable** max_prev = NULL;
   size_t max_ind;
 
   size_t i = _fine_eviction_start;
@@ -599,6 +599,7 @@
   }
 
   guarantee(max != NULL, "Since _n_fine_entries > 0");
+  guarantee(max_prev != NULL, "Since max != NULL.");
 
   // Set the corresponding coarse bit.
   size_t max_hrm_index = (size_t) max->hr()->hrm_index();
@@ -1138,7 +1139,7 @@
 
 void HeapRegionRemSet::print_recorded() {
   int cur_evnt = 0;
-  Event cur_evnt_kind;
+  Event cur_evnt_kind = Event_illegal;
   int cur_evnt_ind = 0;
   if (_n_recorded_events > 0) {
     cur_evnt_kind = _recorded_events[cur_evnt];
--- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -222,7 +222,7 @@
 
 public:
   enum Event {
-    Event_EvacStart, Event_EvacEnd, Event_RSUpdateEnd
+    Event_EvacStart, Event_EvacEnd, Event_RSUpdateEnd, Event_illegal
   };
 
 private:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/workerDataArray.inline.hpp"
+
+#ifndef PRODUCT
+void WorkerDataArray_test() {
+  const uint length = 3;
+  const char* title = "Test array";
+  const bool print_sum = false;
+  const int log_level = 3;
+  const uint indent_level = 2;
+
+  WorkerDataArray<size_t> array(length, title, print_sum, log_level, indent_level);
+  assert(strncmp(array.title(), title, strlen(title)) == 0 , "Expected titles to match");
+  assert(array.should_print_sum() == print_sum, "Expected should_print_sum to match print_sum");
+  assert(array.log_level() == log_level, "Expected log levels to match");
+  assert(array.indentation() == indent_level, "Expected indentation to match");
+
+  const size_t expected[length] = {5, 3, 7};
+  for (uint i = 0; i < length; i++) {
+    array.set(i, expected[i]);
+  }
+  for (uint i = 0; i < length; i++) {
+    assert(array.get(i) == expected[i], "Expected elements to match");
+  }
+
+  assert(array.sum(length) == (5 + 3 + 7), "Expected sums to match");
+  assert(array.minimum(length) == 3, "Expected mininum to match");
+  assert(array.maximum(length) == 7, "Expected maximum to match");
+  assert(array.diff(length) == (7 - 3), "Expected diffs to match");
+  assert(array.average(length) == 5, "Expected averages to match");
+
+  for (uint i = 0; i < length; i++) {
+    array.add(i, 1);
+  }
+  for (uint i = 0; i < length; i++) {
+    assert(array.get(i) == expected[i] + 1, "Expected add to increment values");
+  }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+
+template <class T>
+class WorkerDataArray  : public CHeapObj<mtGC> {
+  friend class G1GCParPhasePrinter;
+  T*          _data;
+  uint        _length;
+  const char* _title;
+  bool        _print_sum;
+  int         _log_level;
+  uint        _indent_level;
+  bool        _enabled;
+
+  WorkerDataArray<size_t>* _thread_work_items;
+
+  NOT_PRODUCT(inline T uninitialized() const;)
+
+  void set_all(T value);
+
+ public:
+  WorkerDataArray(uint length,
+                  const char* title,
+                  bool print_sum,
+                  int log_level,
+                  uint indent_level);
+
+  ~WorkerDataArray();
+
+  void link_thread_work_items(WorkerDataArray<size_t>* thread_work_items);
+  void set_thread_work_item(uint worker_i, size_t value);
+  WorkerDataArray<size_t>* thread_work_items() const {
+    return _thread_work_items;
+  }
+
+  void set(uint worker_i, T value);
+  T get(uint worker_i) const;
+
+  void add(uint worker_i, T value);
+
+  double average(uint active_threads) const;
+  T sum(uint active_threads) const;
+  T minimum(uint active_threads) const;
+  T maximum(uint active_threads) const;
+  T diff(uint active_threads) const;
+
+  uint indentation() const {
+    return _indent_level;
+  }
+
+  const char* title() const {
+    return _title;
+  }
+
+  bool should_print_sum() const {
+    return _print_sum;
+  }
+
+  int log_level() const {
+    return _log_level;
+  }
+
+  void clear();
+  void set_enabled(bool enabled) {
+    _enabled = enabled;
+  }
+
+  void reset() PRODUCT_RETURN;
+  void verify(uint active_threads) const PRODUCT_RETURN;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "gc/g1/workerDataArray.hpp"
+#include "memory/allocation.inline.hpp"
+
+template <typename T>
+WorkerDataArray<T>::WorkerDataArray(uint length,
+                                    const char* title,
+                                    bool print_sum,
+                                    int log_level,
+                                    uint indent_level) :
+ _title(title),
+ _length(0),
+ _print_sum(print_sum),
+ _log_level(log_level),
+ _indent_level(indent_level),
+ _thread_work_items(NULL),
+ _enabled(true) {
+  assert(length > 0, "Must have some workers to store data for");
+  _length = length;
+  _data = NEW_C_HEAP_ARRAY(T, _length, mtGC);
+  reset();
+}
+
+template <typename T>
+void WorkerDataArray<T>::set(uint worker_i, T value) {
+  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
+  assert(_data[worker_i] == uninitialized(), "Overwriting data for worker %d in %s", worker_i, _title);
+  _data[worker_i] = value;
+}
+
+template <typename T>
+T WorkerDataArray<T>::get(uint worker_i) const {
+  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
+  assert(_data[worker_i] != uninitialized(), "No data added for worker %d", worker_i);
+  return _data[worker_i];
+}
+
+template <typename T>
+WorkerDataArray<T>::~WorkerDataArray() {
+  FREE_C_HEAP_ARRAY(T, _data);
+}
+
+template <typename T>
+void WorkerDataArray<T>::link_thread_work_items(WorkerDataArray<size_t>* thread_work_items) {
+  _thread_work_items = thread_work_items;
+}
+
+template <typename T>
+void WorkerDataArray<T>::set_thread_work_item(uint worker_i, size_t value) {
+  assert(_thread_work_items != NULL, "No sub count");
+  _thread_work_items->set(worker_i, value);
+}
+
+template <typename T>
+void WorkerDataArray<T>::add(uint worker_i, T value) {
+  assert(worker_i < _length, "Worker %d is greater than max: %d", worker_i, _length);
+  assert(_data[worker_i] != uninitialized(), "No data to add to for worker %d", worker_i);
+  _data[worker_i] += value;
+}
+
+template <typename T>
+double WorkerDataArray<T>::average(uint active_threads) const {
+  return sum(active_threads) / (double) active_threads;
+}
+
+template <typename T>
+T WorkerDataArray<T>::sum(uint active_threads) const {
+  T s = get(0);
+  for (uint i = 1; i < active_threads; ++i) {
+    s += get(i);
+  }
+  return s;
+}
+
+template <typename T>
+T WorkerDataArray<T>::minimum(uint active_threads) const {
+  T min = get(0);
+  for (uint i = 1; i < active_threads; ++i) {
+    min = MIN2(min, get(i));
+  }
+  return min;
+}
+
+template <typename T>
+T WorkerDataArray<T>::maximum(uint active_threads) const {
+  T max = get(0);
+  for (uint i = 1; i < active_threads; ++i) {
+    max = MAX2(max, get(i));
+  }
+  return max;
+}
+
+template <typename T>
+T WorkerDataArray<T>::diff(uint active_threads) const {
+  return maximum(active_threads) - minimum(active_threads);
+}
+
+template <typename T>
+void WorkerDataArray<T>::clear() {
+  set_all(0);
+}
+
+template <typename T>
+void WorkerDataArray<T>::set_all(T value) {
+  for (uint i = 0; i < _length; i++) {
+    _data[i] = value;
+  }
+}
+
+#ifndef PRODUCT
+template <typename T>
+void WorkerDataArray<T>::reset() {
+  set_all(uninitialized());
+  if (_thread_work_items != NULL) {
+    _thread_work_items->reset();
+  }
+}
+
+template <typename T>
+void WorkerDataArray<T>::verify(uint active_threads) const {
+  if (!_enabled) {
+    return;
+  }
+
+  assert(active_threads <= _length, "Wrong number of active threads");
+  for (uint i = 0; i < active_threads; i++) {
+    assert(_data[i] != uninitialized(),
+           "Invalid data for worker %u in '%s'", i, _title);
+  }
+  if (_thread_work_items != NULL) {
+    _thread_work_items->verify(active_threads);
+  }
+}
+
+template <>
+inline size_t WorkerDataArray<size_t>::uninitialized() const {
+  return (size_t)-1;
+}
+
+template <>
+inline double WorkerDataArray<double>::uninitialized() const {
+  return -1.0;
+}
+#endif
--- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -200,7 +200,7 @@
     // by calling follow_class_loader explicitly. For non-anonymous classes
     // the call to follow_class_loader is made when the class loader itself
     // is handled.
-    if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
+    if (klass->is_instance_klass() && InstanceKlass::cast(klass)->is_anonymous()) {
       cm->follow_class_loader(klass->class_loader_data());
     } else {
       cm->follow_klass(klass);
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -383,7 +383,7 @@
 
   size_t old_size = gch->old_gen()->capacity();
   size_t new_size_before = _virtual_space.committed_size();
-  size_t min_new_size = spec()->init_size();
+  size_t min_new_size = initial_size();
   size_t max_new_size = reserved().byte_size();
   assert(min_new_size <= new_size_before &&
          new_size_before <= max_new_size,
--- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -66,13 +66,6 @@
   const char* name() const { return "tenured generation"; }
   const char* short_name() const { return "Tenured"; }
 
-  // Does a "full" (forced) collection invoked on this generation collect
-  // the young generation as well? Note that this is a hack to allow the
-  // collection of the young gen first if the flag is set.
-  virtual bool full_collects_young_generation() const {
-    return !ScavengeBeforeFullGC;
-  }
-
   size_t unsafe_max_alloc_nogc() const;
   size_t contiguous_available() const;
 
--- a/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/shared/cardGeneration.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -208,8 +208,7 @@
   const double min_tmp = used_after_gc / maximum_used_percentage;
   size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
   // Don't shrink less than the initial generation size
-  minimum_desired_capacity = MAX2(minimum_desired_capacity,
-                                  spec()->init_size());
+  minimum_desired_capacity = MAX2(minimum_desired_capacity, initial_size());
   assert(used_after_gc <= minimum_desired_capacity, "sanity check");
 
   if (PrintGC && Verbose) {
@@ -262,8 +261,7 @@
     const double minimum_used_percentage = 1.0 - maximum_free_percentage;
     const double max_tmp = used_after_gc / minimum_used_percentage;
     size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
-    maximum_desired_capacity = MAX2(maximum_desired_capacity,
-                                    spec()->init_size());
+    maximum_desired_capacity = MAX2(maximum_desired_capacity, initial_size());
     if (PrintGC && Verbose) {
       gclog_or_tty->print_cr("  "
                              "  maximum_free_percentage: %6.2f"
@@ -299,20 +297,20 @@
       }
       if (PrintGC && Verbose) {
         gclog_or_tty->print_cr("  "
-                      "  shrinking:"
-                      "  initSize: %.1fK"
-                      "  maximum_desired_capacity: %.1fK",
-                      spec()->init_size() / (double) K,
-                      maximum_desired_capacity / (double) K);
+                               "  shrinking:"
+                               "  initSize: %.1fK"
+                               "  maximum_desired_capacity: %.1fK",
+                               initial_size() / (double) K,
+                               maximum_desired_capacity / (double) K);
         gclog_or_tty->print_cr("  "
-                      "  shrink_bytes: %.1fK"
-                      "  current_shrink_factor: " SIZE_FORMAT
-                      "  new shrink factor: " SIZE_FORMAT
-                      "  _min_heap_delta_bytes: %.1fK",
-                      shrink_bytes / (double) K,
-                      current_shrink_factor,
-                      _shrink_factor,
-                      _min_heap_delta_bytes / (double) K);
+                               "  shrink_bytes: %.1fK"
+                               "  current_shrink_factor: " SIZE_FORMAT
+                               "  new shrink factor: " SIZE_FORMAT
+                               "  _min_heap_delta_bytes: %.1fK",
+                               shrink_bytes / (double) K,
+                               current_shrink_factor,
+                               _shrink_factor,
+                               _min_heap_delta_bytes / (double) K);
       }
     }
   }
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -66,6 +66,7 @@
 }
 
 void ConcurrentGCThread::terminate() {
+  assert(_should_terminate, "Should only be called on terminate request.");
   // Signal that it is terminated
   {
     MutexLockerEx mu(Terminator_lock,
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -460,10 +460,9 @@
 
     bool prepared_for_verification = false;
     bool collected_old = false;
-    bool old_collects_young = complete &&
-                              _old_gen->full_collects_young_generation();
-    if (!old_collects_young &&
-        _young_gen->should_collect(full, size, is_tlab)) {
+    bool old_collects_young = complete && !ScavengeBeforeFullGC;
+
+    if (!old_collects_young && _young_gen->should_collect(full, size, is_tlab)) {
       if (run_verification && VerifyGCLevel <= 0 && VerifyBeforeGC) {
         prepare_for_verify();
         prepared_for_verification = true;
@@ -1107,10 +1106,6 @@
   _young_gen->prepare_for_compaction(&cp);
 }
 
-GCStats* GenCollectedHeap::gc_stats(Generation* gen) const {
-  return gen->gc_stats();
-}
-
 void GenCollectedHeap::verify(bool silent, VerifyOption option /* ignored */) {
   if (!silent) {
     gclog_or_tty->print("%s", _old_gen->name());
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -126,8 +126,6 @@
 
   WorkGang* workers() const { return _workers; }
 
-  GCStats* gc_stats(Generation* generation) const;
-
   // Returns JNI_OK on success
   virtual jint initialize();
 
--- a/hotspot/src/share/vm/gc/shared/generation.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/shared/generation.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -58,12 +58,12 @@
           (HeapWord*)_virtual_space.high_boundary());
 }
 
-GenerationSpec* Generation::spec() {
+size_t Generation::initial_size() {
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   if (gch->is_young_gen(this)) {
-    return gch->gen_policy()->young_gen_spec();
+    return gch->gen_policy()->young_gen_spec()->init_size();
   }
-  return gch->gen_policy()->old_gen_spec();
+  return gch->gen_policy()->old_gen_spec()->init_size();
 }
 
 size_t Generation::max_capacity() const {
--- a/hotspot/src/share/vm/gc/shared/generation.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/shared/generation.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -141,14 +141,14 @@
   }
 
   virtual Generation::Name kind() { return Generation::Other; }
-  GenerationSpec* spec();
 
   // This properly belongs in the collector, but for now this
   // will do.
   virtual bool refs_discovery_is_atomic() const { return true;  }
   virtual bool refs_discovery_is_mt()     const { return false; }
 
-  // Space enquiries (results in bytes)
+  // Space inquiries (results in bytes)
+  size_t initial_size();
   virtual size_t capacity() const = 0;  // The maximum number of object bytes the
                                         // generation can currently hold.
   virtual size_t used() const = 0;      // The number of used bytes in the gen.
@@ -309,10 +309,6 @@
   // do nothing.
   virtual void par_oop_since_save_marks_iterate_done(int thread_num) {}
 
-  // This generation will collect all younger generations
-  // during a full collection.
-  virtual bool full_collects_young_generation() const { return false; }
-
   // This generation does in-place marking, meaning that mark words
   // are mutated during the marking phase and presumably reinitialized
   // to a canonical value after the GC. This is currently used by the
@@ -403,7 +399,7 @@
   // that was most recently collected. This allows the generation to
   // decide what statistics are valid to collect. For example, the
   // generation can decide to gather the amount of promoted data if
-  // the collection of the younger generations has completed.
+  // the collection of the young generation has completed.
   GCStats* gc_stats() const { return _gc_stats; }
   virtual void update_gc_stats(Generation* current_generation, bool full) {}
 
--- a/hotspot/src/share/vm/gc/shared/generationSpec.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/shared/generationSpec.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -58,9 +58,7 @@
       // else registers with an existing CMSCollector
 
       ConcurrentMarkSweepGeneration* g = NULL;
-      g = new ConcurrentMarkSweepGeneration(rs,
-                 init_size(), remset, UseCMSAdaptiveFreeLists,
-                 (FreeBlockDictionary<FreeChunk>::DictionaryChoice)CMSDictionaryChoice);
+      g = new ConcurrentMarkSweepGeneration(rs, init_size(), remset);
 
       g->initialize_performance_counters();
 
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -373,7 +373,8 @@
   // so that the References are not considered active.
   while (obj != next_d) {
     obj = next_d;
-    assert(obj->is_instanceRef(), "should be reference object");
+    assert(obj->is_instance(), "should be an instance object");
+    assert(InstanceKlass::cast(obj->klass())->is_reference_instance_klass(), "should be reference object");
     next_d = java_lang_ref_Reference::discovered(obj);
     if (TraceReferenceGC && PrintGCDetails) {
       gclog_or_tty->print_cr("        obj " INTPTR_FORMAT "/next_d " INTPTR_FORMAT,
--- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -194,7 +194,7 @@
                                      bool is_bottom_frame);
 
   // Runtime support
-  static bool       is_not_reached(                       methodHandle method, int bci);
+  static bool       is_not_reached(const methodHandle& method, int bci);
   // Safepoint support
   static void       notice_safepoints()                         { ShouldNotReachHere(); } // stops the thread when reaching a safepoint
   static void       ignore_safepoints()                         { ShouldNotReachHere(); } // ignores safepoints
--- a/hotspot/src/share/vm/interpreter/bytecode.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecode.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -179,7 +179,7 @@
  protected:
   const methodHandle _method;                          // method containing the bytecode
 
-  Bytecode_member_ref(methodHandle method, int bci)  : Bytecode(method(), method()->bcp_from(bci)), _method(method) {}
+  Bytecode_member_ref(const methodHandle& method, int bci)  : Bytecode(method(), method()->bcp_from(bci)), _method(method) {}
 
   methodHandle method() const                    { return _method; }
   ConstantPool* constants() const              { return _method->constants(); }
@@ -201,10 +201,10 @@
 class Bytecode_invoke: public Bytecode_member_ref {
  protected:
   // Constructor that skips verification
-  Bytecode_invoke(methodHandle method, int bci, bool unused)  : Bytecode_member_ref(method, bci) {}
+  Bytecode_invoke(const methodHandle& method, int bci, bool unused)  : Bytecode_member_ref(method, bci) {}
 
  public:
-  Bytecode_invoke(methodHandle method, int bci)  : Bytecode_member_ref(method, bci) { verify(); }
+  Bytecode_invoke(const methodHandle& method, int bci)  : Bytecode_member_ref(method, bci) { verify(); }
   void verify() const;
 
   // Attributes
@@ -232,10 +232,10 @@
 
  private:
   // Helper to skip verification.   Used is_valid() to check if the result is really an invoke
-  inline friend Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci);
+  inline friend Bytecode_invoke Bytecode_invoke_check(const methodHandle& method, int bci);
 };
 
-inline Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci) {
+inline Bytecode_invoke Bytecode_invoke_check(const methodHandle& method, int bci) {
   return Bytecode_invoke(method, bci, false);
 }
 
@@ -243,7 +243,7 @@
 // Abstraction for all field accesses (put/get field/static)
 class Bytecode_field: public Bytecode_member_ref {
  public:
-  Bytecode_field(methodHandle method, int bci)  : Bytecode_member_ref(method, bci) { verify(); }
+  Bytecode_field(const methodHandle& method, int bci)  : Bytecode_member_ref(method, bci) { verify(); }
 
   // Testers
   bool is_getfield() const                       { return java_code() == Bytecodes::_getfield; }
@@ -316,7 +316,7 @@
   int raw_index() const;
 
  public:
-  Bytecode_loadconstant(methodHandle method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); }
+  Bytecode_loadconstant(const methodHandle& method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); }
 
   void verify() const {
     assert(_method.not_null(), "must supply method");
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -2148,11 +2148,8 @@
         if (!constants->tag_at(index).is_unresolved_klass()) {
           // Make sure klass is initialized and doesn't have a finalizer
           Klass* entry = constants->slot_at(index).get_klass();
-          assert(entry->is_klass(), "Should be resolved klass");
-          Klass* k_entry = (Klass*) entry;
-          assert(k_entry->oop_is_instance(), "Should be InstanceKlass");
-          InstanceKlass* ik = (InstanceKlass*) k_entry;
-          if ( ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
+          InstanceKlass* ik = InstanceKlass::cast(entry);
+          if (ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
             size_t obj_size = ik->size_helper();
             oop result = NULL;
             // If the TLAB isn't pre-zeroed then we'll have to do it
@@ -2609,9 +2606,9 @@
                   - klass: {other class}
 
                   but using InstanceKlass::cast(STACK_OBJECT(-parms)->klass()) causes in assertion failure
-                  because rcvr->klass()->oop_is_instance() == 0
+                  because rcvr->klass()->is_instance_klass() == 0
                   However it seems to have a vtable in the right location. Huh?
-
+                  Because vtables have the same offset for ArrayKlass and InstanceKlass.
               */
               callee = (Method*) rcvrKlass->start_of_vtable()[ cache->f2_as_index()];
               // Profile virtual call.
--- a/hotspot/src/share/vm/interpreter/bytecodeStream.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeStream.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +63,7 @@
   bool            _is_raw;                       // false in 'cooked' BytecodeStream
 
   // Construction
-  BaseBytecodeStream(methodHandle method) : _method(method) {
+  BaseBytecodeStream(const methodHandle& method) : _method(method) {
     set_interval(0, _method->code_size());
     _is_raw = false;
   }
@@ -118,7 +118,7 @@
 class RawBytecodeStream: public BaseBytecodeStream {
  public:
   // Construction
-  RawBytecodeStream(methodHandle method) : BaseBytecodeStream(method) {
+  RawBytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) {
     _is_raw = true;
   }
 
@@ -169,7 +169,7 @@
 
  public:
   // Construction
-  BytecodeStream(methodHandle method) : BaseBytecodeStream(method) { }
+  BytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) { }
 
   // Iteration
   Bytecodes::Code next() {
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -84,7 +84,7 @@
 
   // This method is called while executing the raw bytecodes, so none of
   // the adjustments that BytecodeStream performs applies.
-  void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) {
+  void trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) {
     ResourceMark rm;
     if (_current_method != method()) {
       // Note 1: This code will not work as expected with true MT/MP.
@@ -126,7 +126,7 @@
 
   // Used for Method*::print_codes().  The input bcp comes from
   // BytecodeStream, which will skip wide bytecodes.
-  void trace(methodHandle method, address bcp, outputStream* st) {
+  void trace(const methodHandle& method, address bcp, outputStream* st) {
     _current_method = method();
     ResourceMark rm;
     Bytecodes::Code code = Bytecodes::code_at(method(), bcp);
@@ -166,7 +166,7 @@
 }
 
 
-void BytecodeTracer::trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) {
+void BytecodeTracer::trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) {
   if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) {
     ttyLocker ttyl;  // 5065316: keep the following output coherent
     // The ttyLocker also prevents races between two threads
@@ -185,7 +185,7 @@
   }
 }
 
-void BytecodeTracer::trace(methodHandle method, address bcp, outputStream* st) {
+void BytecodeTracer::trace(const methodHandle& method, address bcp, outputStream* st) {
   ttyLocker ttyl;  // 5065316: keep the following output coherent
   _closure->trace(method, bcp, st);
 }
@@ -390,7 +390,6 @@
 }
 
 
-PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
 void BytecodePrinter::print_attributes(int bci, outputStream* st) {
   // Show attributes of pre-rewritten codes
   Bytecodes::Code code = Bytecodes::java_code(raw_code());
@@ -512,15 +511,11 @@
         }
         st->print(" %d " INT32_FORMAT " " INT32_FORMAT " ",
                       default_dest, lo, hi);
-        int first = true;
-        for (int ll = lo; ll <= hi; ll++, first = false)  {
+        const char *comma = "";
+        for (int ll = lo; ll <= hi; ll++) {
           int idx = ll - lo;
-          const char *format = first ? " %d:" INT32_FORMAT " (delta: %d)" :
-                                       ", %d:" INT32_FORMAT " (delta: %d)";
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-          st->print(format, ll, dest[idx], dest[idx]-bci);
-PRAGMA_DIAG_POP
+          st->print("%s %d:" INT32_FORMAT " (delta: %d)", comma, ll, dest[idx], dest[idx]-bci);
+          comma = ",";
         }
         st->cr();
       }
@@ -536,14 +531,10 @@
           dest[i] = bci + get_int();
         };
         st->print(" %d %d ", default_dest, len);
-        bool first = true;
-        for (int ll = 0; ll < len; ll++, first = false)  {
-          const char *format = first ? " " INT32_FORMAT ":" INT32_FORMAT :
-                                       ", " INT32_FORMAT ":" INT32_FORMAT ;
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-          st->print(format, key[ll], dest[ll]);
-PRAGMA_DIAG_POP
+        const char *comma = "";
+        for (int ll = 0; ll < len; ll++)  {
+          st->print("%s " INT32_FORMAT ":" INT32_FORMAT, comma, key[ll], dest[ll]);
+          comma = ",";
         }
         st->cr();
       }
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,8 +46,8 @@
   static BytecodeClosure* closure()                                                   { return _closure; }
   static void             set_closure(BytecodeClosure* closure) { _closure = closure; }
 
-  static void             trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st = tty);
-  static void             trace(methodHandle method, address bcp, outputStream* st = tty);
+  static void             trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st = tty);
+  static void             trace(const methodHandle& method, address bcp, outputStream* st = tty);
 };
 
 
@@ -55,8 +55,8 @@
 
 class BytecodeClosure {
  public:
-  virtual void trace(methodHandle method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) = 0;
-  virtual void trace(methodHandle method, address bcp, outputStream* st) = 0;
+  virtual void trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) = 0;
+  virtual void trace(const methodHandle& method, address bcp, outputStream* st) = 0;
 };
 
 #endif // SHARE_VM_INTERPRETER_BYTECODETRACER_HPP
--- a/hotspot/src/share/vm/interpreter/interpreter.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -320,7 +320,7 @@
 
 // Return true if the interpreter can prove that the given bytecode has
 // not yet been executed (in Java semantics, not in actual operation).
-bool AbstractInterpreter::is_not_reached(methodHandle method, int bci) {
+bool AbstractInterpreter::is_not_reached(const methodHandle& method, int bci) {
   Bytecodes::Code code = method()->code_at(bci);
 
   if (!Bytecodes::must_rewrite(code)) {
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -480,7 +480,7 @@
   } while (should_repeat == true);
 
 #if INCLUDE_JVMCI
-  if (UseJVMCICompiler && h_method->method_data() != NULL) {
+  if (EnableJVMCI && h_method->method_data() != NULL) {
     ResourceMark rm(thread);
     ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci, NULL);
     if (pdata != NULL && pdata->is_BitData()) {
@@ -1192,7 +1192,7 @@
   return handler;
 }
 
-void SignatureHandlerLibrary::add(methodHandle method) {
+void SignatureHandlerLibrary::add(const methodHandle& method) {
   if (method->signature_handler() == NULL) {
     // use slow signature handler if we can't do better
     int handler_index = -1;
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -218,7 +218,7 @@
   static void pd_set_handler(address handler);
 
  public:
-  static void add(methodHandle method);
+  static void add(const methodHandle& method);
   static void add(uint64_t fingerprint, address handler);
 };
 
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -237,7 +237,7 @@
 //------------------------------------------------------------------------------------------------------------------------
 // Implementation of LinkInfo
 
-LinkInfo::LinkInfo(constantPoolHandle pool, int index, TRAPS) {
+LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) {
    // resolve klass
   Klass* result = pool->klass_ref_at(index, CHECK);
   _resolved_klass = KlassHandle(THREAD, result);
@@ -302,17 +302,19 @@
   // Ignore overpasses so statics can be found during resolution
   Method* result = klass->uncached_lookup_method(name, signature, Klass::skip_overpass);
 
-  if (klass->oop_is_array()) {
+  if (klass->is_array_klass()) {
     // Only consider klass and super klass for arrays
     return methodHandle(THREAD, result);
   }
 
+  InstanceKlass* ik = InstanceKlass::cast(klass());
+
   // JDK 8, JVMS 5.4.3.4: Interface method resolution should
   // ignore static and non-public methods of java.lang.Object,
   // like clone, finalize, registerNatives.
   if (in_imethod_resolve &&
       result != NULL &&
-      klass->is_interface() &&
+      ik->is_interface() &&
       (result->is_static() || !result->is_public()) &&
       result->method_holder() == SystemDictionary::Object_klass()) {
     result = NULL;
@@ -321,11 +323,11 @@
   // Before considering default methods, check for an overpass in the
   // current class if a method has not been found.
   if (result == NULL) {
-    result = InstanceKlass::cast(klass())->find_method(name, signature);
+    result = ik->find_method(name, signature);
   }
 
   if (result == NULL) {
-    Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
+    Array<Method*>* default_methods = ik->default_methods();
     if (default_methods != NULL) {
       result = InstanceKlass::find_method(default_methods, name, signature);
     }
@@ -353,7 +355,7 @@
     result = super_klass->uncached_lookup_method(name, signature, Klass::find_overpass);
   }
 
-  if (klass->oop_is_array()) {
+  if (klass->is_array_klass()) {
     // Only consider klass and super klass for arrays
     return methodHandle(THREAD, result);
   }
@@ -374,21 +376,21 @@
   int vtable_index = Method::invalid_vtable_index;
   Symbol* name = resolved_method->name();
   Symbol* signature = resolved_method->signature();
+  InstanceKlass* ik = InstanceKlass::cast(klass());
 
   // First check in default method array
-  if (!resolved_method->is_abstract() &&
-    (InstanceKlass::cast(klass())->default_methods() != NULL)) {
-    int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(),
+  if (!resolved_method->is_abstract() && ik->default_methods() != NULL) {
+    int index = InstanceKlass::find_method_index(ik->default_methods(),
                                                  name, signature, Klass::find_overpass,
                                                  Klass::find_static, Klass::find_private);
     if (index >= 0 ) {
-      vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
+      vtable_index = ik->default_vtable_indices()->at(index);
     }
   }
   if (vtable_index == Method::invalid_vtable_index) {
     // get vtable_index for miranda methods
     ResourceMark rm;
-    klassVtable *vt = InstanceKlass::cast(klass())->vtable();
+    klassVtable *vt = ik->vtable();
     vtable_index = vt->index_of_miranda(name, signature);
   }
   return vtable_index;
@@ -529,7 +531,7 @@
   // to be false (so we'll short-circuit out of these tests).
   if (sel_method->name() == vmSymbols::clone_name() &&
       sel_klass() == SystemDictionary::Object_klass() &&
-      resolved_klass->oop_is_array()) {
+      resolved_klass->is_array_klass()) {
     // We need to change "protected" to "public".
     assert(flags.is_protected(), "clone not protected?");
     jint new_flags = flags.as_int();
@@ -559,7 +561,7 @@
 }
 
 methodHandle LinkResolver::resolve_method_statically(Bytecodes::Code code,
-                                                     constantPoolHandle pool, int index, TRAPS) {
+                                                     const constantPoolHandle& pool, int index, TRAPS) {
   // This method is used only
   // (1) in C2 from InlineTree::ok_to_inline (via ciMethod::check_call),
   // and
@@ -682,7 +684,7 @@
   // 2. lookup method in resolved klass and its super klasses
   methodHandle resolved_method = lookup_method_in_klasses(link_info, true, false, CHECK_NULL);
 
-  if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // not found in the class hierarchy
+  if (resolved_method.is_null() && !resolved_klass->is_array_klass()) { // not found in the class hierarchy
     // 3. lookup method in all the interfaces implemented by the resolved klass
     resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
 
@@ -742,7 +744,7 @@
   // JDK8: also look for static methods
   methodHandle resolved_method = lookup_method_in_klasses(link_info, false, true, CHECK_NULL);
 
-  if (resolved_method.is_null() && !resolved_klass->oop_is_array()) {
+  if (resolved_method.is_null() && !resolved_klass->is_array_klass()) {
     // lookup method in all the super-interfaces
     resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
   }
@@ -816,7 +818,7 @@
   }
 }
 
-void LinkResolver::resolve_field_access(fieldDescriptor& fd, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
+void LinkResolver::resolve_field_access(fieldDescriptor& fd, const constantPoolHandle& pool, int index, Bytecodes::Code byte, TRAPS) {
   LinkInfo link_info(pool, index, CHECK);
   resolve_field(fd, link_info, byte, true, CHECK);
 }
@@ -1442,7 +1444,7 @@
 //------------------------------------------------------------------------------------------------------------------------
 // ConstantPool entries
 
-void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
+void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, Bytecodes::Code byte, TRAPS) {
   switch (byte) {
     case Bytecodes::_invokestatic   : resolve_invokestatic   (result,       pool, index, CHECK); break;
     case Bytecodes::_invokespecial  : resolve_invokespecial  (result,       pool, index, CHECK); break;
@@ -1454,20 +1456,20 @@
   return;
 }
 
-void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
+void LinkResolver::resolve_invokestatic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) {
   LinkInfo link_info(pool, index, CHECK);
   resolve_static_call(result, link_info, /*initialize_class*/true, CHECK);
 }
 
 
-void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
+void LinkResolver::resolve_invokespecial(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) {
   LinkInfo link_info(pool, index, CHECK);
   resolve_special_call(result, link_info, CHECK);
 }
 
 
 void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv,
-                                          constantPoolHandle pool, int index,
+                                          const constantPoolHandle& pool, int index,
                                           TRAPS) {
 
   LinkInfo link_info(pool, index, CHECK);
@@ -1476,14 +1478,14 @@
 }
 
 
-void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) {
+void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS) {
   LinkInfo link_info(pool, index, CHECK);
   KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass());
   resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK);
 }
 
 
-void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
+void LinkResolver::resolve_invokehandle(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) {
   // This guy is reached from InterpreterRuntime::resolve_invokehandle.
   LinkInfo link_info(pool, index, CHECK);
   if (TraceMethodHandles) {
@@ -1528,7 +1530,7 @@
   }
 }
 
-void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
+void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) {
   Symbol* method_name       = pool->name_ref_at(index);
   Symbol* method_signature  = pool->signature_ref_at(index);
   KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder());
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -136,7 +136,7 @@
   KlassHandle _current_klass;   // class that owns the constant pool
   bool        _check_access;
  public:
-  LinkInfo(constantPoolHandle pool, int index, TRAPS);
+  LinkInfo(const constantPoolHandle& pool, int index, TRAPS);
   // Condensed information from other call sites within the vm.
   LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
            KlassHandle current_klass, bool check_access = true) :
@@ -226,17 +226,17 @@
 
   // runtime resolving from constant pool
   static void resolve_invokestatic   (CallInfo& result,
-                                      constantPoolHandle pool, int index, TRAPS);
+                                      const constantPoolHandle& pool, int index, TRAPS);
   static void resolve_invokespecial  (CallInfo& result,
-                                      constantPoolHandle pool, int index, TRAPS);
+                                      const constantPoolHandle& pool, int index, TRAPS);
   static void resolve_invokevirtual  (CallInfo& result, Handle recv,
-                                      constantPoolHandle pool, int index, TRAPS);
+                                      const constantPoolHandle& pool, int index, TRAPS);
   static void resolve_invokeinterface(CallInfo& result, Handle recv,
-                                      constantPoolHandle pool, int index, TRAPS);
+                                      const constantPoolHandle& pool, int index, TRAPS);
   static void resolve_invokedynamic  (CallInfo& result,
-                                      constantPoolHandle pool, int index, TRAPS);
+                                      const constantPoolHandle& pool, int index, TRAPS);
   static void resolve_invokehandle   (CallInfo& result,
-                                      constantPoolHandle pool, int index, TRAPS);
+                                      const constantPoolHandle& pool, int index, TRAPS);
  public:
   // constant pool resolving
   static void check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS);
@@ -244,11 +244,11 @@
   // static resolving calls (will not run any Java code);
   // used only from Bytecode_invoke::static_target
   static methodHandle resolve_method_statically(Bytecodes::Code code,
-                                                constantPoolHandle pool,
+                                                const constantPoolHandle& pool,
                                                 int index, TRAPS);
 
   static void resolve_field_access(fieldDescriptor& result,
-                                   constantPoolHandle pool,
+                                   const constantPoolHandle& pool,
                                    int index, Bytecodes::Code byte, TRAPS);
   static void resolve_field(fieldDescriptor& result, const LinkInfo& link_info,
                             Bytecodes::Code access_kind,
@@ -293,7 +293,7 @@
 
   // runtime resolving from constant pool
   static void resolve_invoke(CallInfo& result, Handle recv,
-                             constantPoolHandle pool, int index,
+                             const constantPoolHandle& pool, int index,
                              Bytecodes::Code byte, TRAPS);
  private:
   static void trace_method_resolution(const char* prefix, KlassHandle klass,
--- a/hotspot/src/share/vm/interpreter/oopMapCache.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/oopMapCache.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -426,7 +426,7 @@
   }
 }
 
-inline unsigned int OopMapCache::hash_value_for(methodHandle method, int bci) const {
+inline unsigned int OopMapCache::hash_value_for(const methodHandle& method, int bci) const {
   // We use method->code_size() rather than method->identity_hash() below since
   // the mark may not be present if a pointer to the method is already reversed.
   return   ((unsigned int) bci)
@@ -477,7 +477,7 @@
     }
 }
 
-void OopMapCache::lookup(methodHandle method,
+void OopMapCache::lookup(const methodHandle& method,
                          int bci,
                          InterpreterOopMap* entry_for) const {
   MutexLocker x(&_mut);
@@ -558,7 +558,7 @@
   return;
 }
 
-void OopMapCache::compute_one_oop_map(methodHandle method, int bci, InterpreterOopMap* entry) {
+void OopMapCache::compute_one_oop_map(const methodHandle& method, int bci, InterpreterOopMap* entry) {
   // Due to the invariants above it's tricky to allocate a temporary OopMapCacheEntry on the stack
   OopMapCacheEntry* tmp = NEW_C_HEAP_ARRAY(OopMapCacheEntry, 1, mtClass);
   tmp->initialize();
--- a/hotspot/src/share/vm/interpreter/oopMapCache.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/oopMapCache.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -116,7 +116,7 @@
   void set_expression_stack_size(int sz)         { _expression_stack_size = sz; }
 
   // Lookup
-  bool match(methodHandle method, int bci) const { return _method == method() && _bci == bci; }
+  bool match(const methodHandle& method, int bci) const { return _method == method() && _bci == bci; }
   bool is_empty() const;
 
   // Initialization
@@ -151,7 +151,7 @@
 
   OopMapCacheEntry* _array;
 
-  unsigned int hash_value_for(methodHandle method, int bci) const;
+  unsigned int hash_value_for(const methodHandle& method, int bci) const;
   OopMapCacheEntry* entry_at(int i) const;
 
   mutable Mutex _mut;
@@ -167,10 +167,10 @@
 
   // Returns the oopMap for (method, bci) in parameter "entry".
   // Returns false if an oop map was not found.
-  void lookup(methodHandle method, int bci, InterpreterOopMap* entry) const;
+  void lookup(const methodHandle& method, int bci, InterpreterOopMap* entry) const;
 
   // Compute an oop map without updating the cache or grabbing any locks (for debugging)
-  static void compute_one_oop_map(methodHandle method, int bci, InterpreterOopMap* entry);
+  static void compute_one_oop_map(const methodHandle& method, int bci, InterpreterOopMap* entry);
 
   // Returns total no. of bytes allocated as part of OopMapCache's
   static long memory_usage()                     PRODUCT_RETURN0;
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -509,7 +509,7 @@
   // (That's all, folks.)
 }
 
-Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS)
+Rewriter::Rewriter(instanceKlassHandle klass, const constantPoolHandle& cpool, Array<Method*>* methods, TRAPS)
   : _klass(klass),
     _pool(cpool),
     _methods(methods)
--- a/hotspot/src/share/vm/interpreter/rewriter.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/rewriter.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -185,7 +185,7 @@
   }
 
   // All the work goes in here:
-  Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS);
+  Rewriter(instanceKlassHandle klass, const constantPoolHandle& cpool, Array<Method*>* methods, TRAPS);
 
   void compute_index_maps();
   void make_constant_pool_cache(TRAPS);
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -562,7 +562,7 @@
   if (StopInterpreterAt > 0)                                     stop_interpreter_at();
   __ verify_FPU(1, t->tos_in());
 #endif // !PRODUCT
-  int step;
+  int step = 0;
   if (!t->does_dispatch()) {
     step = t->is_wide() ? Bytecodes::wide_length_for(t->bytecode()) : Bytecodes::length_for(t->bytecode());
     if (tos_out == ilgl) tos_out = t->tos_out();
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -142,42 +142,38 @@
   return map;
 }
 
-static void record_metadata_reference(oop obj, jlong prim, jboolean compressed, OopRecorder* oop_recorder) {
+Metadata* CodeInstaller::record_metadata_reference(Handle& constant) {
+  oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
   if (obj->is_a(HotSpotResolvedObjectTypeImpl::klass())) {
     Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
-    if (compressed) {
-      assert(Klass::decode_klass((narrowKlass) prim) == klass, "%s @ " INTPTR_FORMAT " != " PTR64_FORMAT, klass->name()->as_C_string(), p2i(klass), prim);
-    } else {
-      assert((Klass*) prim == klass, "%s @ " INTPTR_FORMAT " != " PTR64_FORMAT, klass->name()->as_C_string(), p2i(klass), prim);
-    }
-    int index = oop_recorder->find_index(klass);
-    TRACE_jvmci_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string());
+    assert(!HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected compressed klass pointer %s @ " INTPTR_FORMAT, klass->name()->as_C_string(), p2i(klass));
+    int index = _oop_recorder->find_index(klass);
+    TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string());
+    return klass;
   } else if (obj->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
     Method* method = (Method*) (address) HotSpotResolvedJavaMethodImpl::metaspaceMethod(obj);
-    assert(!compressed, "unexpected compressed method pointer %s @ " INTPTR_FORMAT " = " PTR64_FORMAT, method->name()->as_C_string(), p2i(method), prim);
-    int index = oop_recorder->find_index(method);
-    TRACE_jvmci_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string());
+    assert(!HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected compressed method pointer %s @ " INTPTR_FORMAT, method->name()->as_C_string(), p2i(method));
+    int index = _oop_recorder->find_index(method);
+    TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), method->name()->as_C_string());
+    return method;
   } else {
-    assert(java_lang_String::is_instance(obj),
-        "unexpected metadata reference (%s) for constant " JLONG_FORMAT " (" PTR64_FORMAT ")", obj->klass()->name()->as_C_string(), prim, prim);
+    fatal("unexpected metadata reference for constant of type %s", obj->klass()->name()->as_C_string());
+    return NULL;
   }
 }
 
-// Records any Metadata values embedded in a Constant (e.g., the value returned by HotSpotResolvedObjectTypeImpl.klass()).
-static void record_metadata_in_constant(oop constant, OopRecorder* oop_recorder) {
-  if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
-    oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
-    jlong prim = HotSpotMetaspaceConstantImpl::primitive(constant);
-    assert(obj != NULL, "must have an object");
-    assert(prim != 0, "must have a primitive value");
+#ifdef _LP64
+narrowKlass CodeInstaller::record_narrow_metadata_reference(Handle& constant) {
+  oop obj = HotSpotMetaspaceConstantImpl::metaspaceObject(constant);
+  assert(HotSpotMetaspaceConstantImpl::compressed(constant), "unexpected uncompressed pointer");
+  assert(obj->is_a(HotSpotResolvedObjectTypeImpl::klass()), "unexpected compressed pointer of type %s", obj->klass()->name()->as_C_string());
 
-    record_metadata_reference(obj, prim, false, oop_recorder);
-  }
+  Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(obj));
+  int index = _oop_recorder->find_index(klass);
+  TRACE_jvmci_3("narrowKlass[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string());
+  return Klass::encode_klass(klass);
 }
-
-static void record_metadata_in_patch(Handle& constant, OopRecorder* oop_recorder) {
-  record_metadata_reference(HotSpotMetaspaceConstantImpl::metaspaceObject(constant), HotSpotMetaspaceConstantImpl::primitive(constant), HotSpotMetaspaceConstantImpl::compressed(constant), oop_recorder);
-}
+#endif
 
 Location::Type CodeInstaller::get_oop_type(oop value) {
   oop lirKind = Value::lirKind(value);
@@ -253,7 +249,6 @@
     }
     return value;
   } else if (value->is_a(JavaConstant::klass())) {
-    record_metadata_in_constant(value, _oop_recorder);
     if (value->is_a(PrimitiveConstant::klass())) {
       if (value->is_a(RawConstant::klass())) {
         jlong prim = PrimitiveConstant::primitive(value);
@@ -379,14 +374,15 @@
       }
     }
   }
-  objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code);
-  if (!methods.is_null()) {
-    int length = methods->length();
-    for (int i = 0; i < length; ++i) {
-      Handle method_handle = methods->obj_at(i);
-      methodHandle method = getMethodFromHotSpotMethod(method_handle());
-
-      _dependencies->assert_evol_method(method());
+  if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
+    objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code);
+    if (!methods.is_null()) {
+      int length = methods->length();
+      for (int i = 0; i < length; ++i) {
+        Handle method_handle = methods->obj_at(i);
+        methodHandle method = getMethodFromHotSpotMethod(method_handle());
+        _dependencies->assert_evol_method(method());
+      }
     }
   }
 }
@@ -543,7 +539,7 @@
 }
 
 int CodeInstaller::estimate_stubs_size() {
-  // Return size for all stubs.
+  // Estimate the number of static call stubs that might be emitted.
   int static_call_stubs = 0;
   objArrayOop sites = this->sites();
   for (int i = 0; i < sites->length(); i++) {
@@ -564,6 +560,7 @@
 
 // perform data and call relocation on the CodeBuffer
 JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer) {
+  HandleMark hm;
   objArrayHandle sites = this->sites();
   int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
 
@@ -606,14 +603,22 @@
     Handle reference = CompilationResult_DataPatch::reference(patch);
     assert(reference->is_a(CompilationResult_ConstantReference::klass()), "patch in data section must be a ConstantReference");
     Handle constant = CompilationResult_ConstantReference::constant(reference);
+    address dest = _constants->start() + CompilationResult_Site::pcOffset(patch);
     if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
-      record_metadata_in_patch(constant, _oop_recorder);
+      if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
+#ifdef _LP64
+        *((narrowKlass*) dest) = record_narrow_metadata_reference(constant);
+#else
+        fatal("unexpected compressed Klass* in 32-bit mode");
+#endif
+      } else {
+        *((Metadata**) dest) = record_metadata_reference(constant);
+      }
     } else if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
       Handle obj = HotSpotObjectConstantImpl::object(constant);
       jobject value = JNIHandles::make_local(obj());
       int oop_index = _oop_recorder->find_index(value);
 
-      address dest = _constants->start() + CompilationResult_Site::pcOffset(patch);
       if (HotSpotObjectConstantImpl::compressed(constant)) {
 #ifdef _LP64
         _constants->relocate(dest, oop_Relocation::spec(oop_index), relocInfo::narrow_oop_in_const);
@@ -960,7 +965,7 @@
     if (constant->is_a(HotSpotObjectConstantImpl::klass())) {
       pd_patch_OopConstant(pc_offset, constant);
     } else if (constant->is_a(HotSpotMetaspaceConstantImpl::klass())) {
-      record_metadata_in_patch(constant, _oop_recorder);
+      pd_patch_MetaspaceConstant(pc_offset, constant);
     } else if (constant->is_a(HotSpotSentinelConstant::klass())) {
       fatal("sentinel constant unsupported");
     } else {
@@ -1014,6 +1019,7 @@
       case POLL_RETURN_FAR:
         pd_relocate_poll(pc, id);
         break;
+      case CARD_TABLE_SHIFT:
       case CARD_TABLE_ADDRESS:
       case HEAP_TOP_ADDRESS:
       case HEAP_END_ADDRESS:
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -107,10 +107,11 @@
     POLL_FAR                   = 13,
     POLL_RETURN_FAR            = 14,
     CARD_TABLE_ADDRESS         = 15,
-    HEAP_TOP_ADDRESS           = 16,
-    HEAP_END_ADDRESS           = 17,
-    NARROW_KLASS_BASE_ADDRESS  = 18,
-    CRC_TABLE_ADDRESS          = 19,
+    CARD_TABLE_SHIFT           = 16,
+    HEAP_TOP_ADDRESS           = 17,
+    HEAP_END_ADDRESS           = 18,
+    NARROW_KLASS_BASE_ADDRESS  = 19,
+    CRC_TABLE_ADDRESS          = 20,
     INVOKE_INVALID             = -1
   };
 
@@ -155,8 +156,8 @@
 
   jint pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method);
   void pd_patch_OopConstant(int pc_offset, Handle& constant);
+  void pd_patch_MetaspaceConstant(int pc_offset, Handle& constant);
   void pd_patch_DataSectionReference(int pc_offset, int data_offset);
-  void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst);
   void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination);
   void pd_relocate_JavaMethod(oop method, jint pc_offset);
   void pd_relocate_poll(address pc, jint mark);
@@ -170,11 +171,10 @@
   objArrayOop comments() { return (objArrayOop) JNIHandles::resolve(_comments_handle); }
 #endif
 
-  void record_resolved(oop obj);
-
   oop word_kind() { return (oop) JNIHandles::resolve(_word_kind_handle); }
 
 public:
+
   CodeInstaller() : _arena(mtCompiler) {}
 
   JVMCIEnv::CodeInstallResult gather_metadata(Handle target, Handle& compiled_code, CodeMetadata& metadata);
@@ -191,6 +191,11 @@
   ScopeValue* get_scope_value(oop value, BasicType type, GrowableArray<ScopeValue*>* objects, ScopeValue* &second);
   MonitorValue* get_monitor_value(oop value, GrowableArray<ScopeValue*>* objects);
 
+  Metadata* record_metadata_reference(Handle& constant);
+#ifdef _LP64
+  narrowKlass record_narrow_metadata_reference(Handle& constant);
+#endif
+
   // extract the fields of the CompilationResult
   void initialize_fields(oop target, oop target_method);
   void initialize_dependencies(oop target_method, OopRecorder* oop_recorder);
--- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,10 @@
 }
 
 void JVMCICompiler::bootstrap() {
+  if (Arguments::mode() == Arguments::_int) {
+    // Nothing to do in -Xint mode
+    return;
+  }
 #ifndef PRODUCT
   // We turn off CompileTheWorld so that compilation requests are not
   // ignored during bootstrap or that JVMCI can be compiled by C1/C2.
@@ -72,7 +76,7 @@
   }
   jlong start = os::javaTimeMillis();
 
-  Array<Method*>* objectMethods = InstanceKlass::cast(SystemDictionary::Object_klass())->methods();
+  Array<Method*>* objectMethods = SystemDictionary::Object_klass()->methods();
   // Initialize compile queue with a selected set of methods.
   int len = objectMethods->length();
   for (int i = 0; i < len; i++) {
@@ -125,22 +129,40 @@
   Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_ABORT);
 
   JavaValue method_result(T_OBJECT);
-  {
+  JavaCallArguments args;
+  args.push_long((jlong) (address) method());
+  JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(),
+                         vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
+
+  if (!HAS_PENDING_EXCEPTION) {
+    JavaValue result(T_VOID);
     JavaCallArguments args;
-    args.push_long((jlong) (address) method());
-    JavaCalls::call_static(&method_result, SystemDictionary::HotSpotResolvedJavaMethodImpl_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::method_fromMetaspace_signature(), &args, CHECK_ABORT);
+    args.push_oop(receiver);
+    args.push_oop((oop)method_result.get_jobject());
+    args.push_int(entry_bci);
+    args.push_long((jlong) (address) env);
+    args.push_int(env->task()->compile_id());
+    JavaCalls::call_special(&result, receiver->klass(),
+                            vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD);
   }
 
-  JavaValue result(T_VOID);
-  JavaCallArguments args;
-  args.push_oop(receiver);
-  args.push_oop((oop)method_result.get_jobject());
-  args.push_int(entry_bci);
-  args.push_long((jlong) (address) env);
-  args.push_int(env->task()->compile_id());
-  JavaCalls::call_special(&result, receiver->klass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, CHECK_ABORT);
+  // An uncaught exception was thrown during compilation.  Generally these
+  // should be handled by the Java code in some useful way but if they leak
+  // through to here report them instead of dying or silently ignoring them.
+  if (HAS_PENDING_EXCEPTION) {
+    Handle throwable = PENDING_EXCEPTION;
+    CLEAR_PENDING_EXCEPTION;
 
-  _methodsCompiled++;
+    JVMCIRuntime::call_printStackTrace(throwable, THREAD);
+    if (HAS_PENDING_EXCEPTION) {
+      CLEAR_PENDING_EXCEPTION;
+    }
+
+    // Something went wrong so disable compilation at this level
+    method->set_not_compilable(CompLevel_full_optimization);
+  } else {
+    _methodsCompiled++;
+  }
 }
 
 
@@ -149,6 +171,13 @@
   ShouldNotReachHere();
 }
 
+bool JVMCICompiler::is_trivial(Method* method) {
+  if (_bootstrapping) {
+    return false;
+  }
+  return JVMCIRuntime::treat_as_trivial(method);
+}
+
 // Print compilation timers and statistics
 void JVMCICompiler::print_timers() {
   print_compilation_timers();
--- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -73,6 +73,8 @@
 
   void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env);
 
+  virtual bool is_trivial(Method* method);
+
   // Print compilation timers and statistics
   virtual void print_timers();
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -60,7 +60,7 @@
 
 #define C2V_END }
 
-oop CompilerToVM::get_jvmci_method(methodHandle method, TRAPS) {
+oop CompilerToVM::get_jvmci_method(const methodHandle& method, TRAPS) {
   if (method() != NULL) {
     JavaValue result(T_OBJECT);
     JavaCallArguments args;
@@ -84,6 +84,24 @@
   return NULL;
 }
 
+void CompilerToVM::invalidate_installed_code(Handle installedCode, TRAPS) {
+  if (installedCode() == NULL) {
+    THROW(vmSymbols::java_lang_NullPointerException());
+  }
+  jlong nativeMethod = InstalledCode::address(installedCode);
+  nmethod* nm = (nmethod*)nativeMethod;
+  assert(nm == NULL || nm->jvmci_installed_code() == installedCode(), "sanity check");
+  if (nm != NULL && nm->is_alive()) {
+    // The nmethod state machinery maintains the link between the
+    // HotSpotInstalledCode and nmethod* so as long as the nmethod appears to be
+    // alive assume there is work to do and deoptimize the nmethod.
+    nm->mark_for_deoptimization();
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+  InstalledCode::set_address(installedCode, 0);
+}
+
 extern "C" {
 extern VMStructEntry* gHotSpotVMStructs;
 extern uint64_t gHotSpotVMStructEntryTypeNameOffset;
@@ -538,8 +556,8 @@
   if (!method->method_holder()->is_interface()) {
     THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Method %s is not held by an interface, this case should be handled in Java code", method->name_and_sig_as_C_string()));
   }
-  if (!InstanceKlass::cast(klass)->is_initialized()) {
-    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Class %s must be initialized", klass->external_name()));
+  if (!InstanceKlass::cast(klass)->is_linked()) {
+    THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Class %s must be linked", klass->external_name()));
   }
   return LinkResolver::vtable_index_of_interface_method(klass, method);
 C2V_END
@@ -549,7 +567,7 @@
   Klass* caller_klass = CompilerToVM::asKlass(caller_jvmci_type);
   Method* method = CompilerToVM::asMethod(jvmci_method);
 
-  if (recv_klass->oop_is_array() || (InstanceKlass::cast(recv_klass)->is_linked())) {
+  if (recv_klass->is_array_klass() || (InstanceKlass::cast(recv_klass)->is_linked())) {
     Klass* holder_klass = method->method_holder();
     Symbol* method_name = method->name();
     Symbol* method_signature = method->signature();
@@ -670,8 +688,13 @@
   } else {
     if (!installed_code_handle.is_null()) {
       assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
+      CompilerToVM::invalidate_installed_code(installed_code_handle, CHECK_0);
       InstalledCode::set_address(installed_code_handle, (jlong) cb);
-      InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1);
+      if (cb->is_nmethod()) {
+        InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->as_nmethod_or_null()->verified_entry_point());
+      } else {
+        InstalledCode::set_entryPoint(installed_code_handle, (jlong) cb->code_begin());
+      }
       if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) {
         HotSpotInstalledCode::set_size(installed_code_handle, cb->size());
         HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin());
@@ -782,10 +805,19 @@
   stats->_osr.reset();
 C2V_END
 
-C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob))
+C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jobject installedCode))
   ResourceMark rm;
   HandleMark hm;
 
+  if (installedCode == NULL) {
+    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "installedCode is null");
+  }
+
+  jlong codeBlob = InstalledCode::address(installedCode);
+  if (codeBlob == 0L) {
+    return NULL;
+  }
+
   CodeBlob* cb = (CodeBlob*) (address) codeBlob;
   if (cb == NULL) {
     return NULL;
@@ -936,15 +968,9 @@
 C2V_END
 
 
-C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject hotspotInstalledCode))
-  jlong nativeMethod = InstalledCode::address(hotspotInstalledCode);
-  nmethod* m = (nmethod*)nativeMethod;
-  if (m != NULL && !m->is_not_entrant()) {
-    m->mark_for_deoptimization();
-    VM_Deoptimize op;
-    VMThread::execute(&op);
-  }
-  InstalledCode::set_address(hotspotInstalledCode, 0);
+C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv*, jobject, jobject installed_code))
+  Handle installed_code_handle = JNIHandles::resolve(installed_code);
+  CompilerToVM::invalidate_installed_code(installed_code_handle, CHECK);
 C2V_END
 
 C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv*, jobject, jlong addr))
@@ -991,7 +1017,8 @@
   objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods);
 
   for (int i = 0; i < methods_oop->length(); i++) {
-    if (CompilerToVM::asMethod(methods_oop->obj_at(i)) == method) {
+    oop resolved = methods_oop->obj_at(i);
+    if (resolved->is_a(HotSpotResolvedJavaMethodImpl::klass()) && CompilerToVM::asMethod(resolved) == method) {
       return true;
     }
   }
@@ -1284,11 +1311,29 @@
   tty->flush();
 C2V_END
 
+C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv*, jobject, jlong metaspace_method_data, jint position))
+  ResourceMark rm;
+  MethodData* mdo = CompilerToVM::asMethodData(metaspace_method_data);
+  ProfileData* profile_data = mdo->data_at(position);
+  if (mdo->is_valid(profile_data)) {
+    return profile_data->size_in_bytes();
+  }
+  DataLayout* data    = mdo->extra_data_base();
+  DataLayout* end   = mdo->extra_data_limit();
+  for (;; data = mdo->next_extra(data)) {
+    assert(data < end, "moved past end of extra data");
+    profile_data = data->data_in();
+    if (mdo->dp_to_di(profile_data->dp()) == position) {
+      return profile_data->size_in_bytes();
+    }
+  }
+  THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Invalid profile data position %d", position));
+C2V_END
+
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
 
-#define SPECULATION_LOG       "Ljdk/vm/ci/meta/SpeculationLog;"
 #define STRING                "Ljava/lang/String;"
 #define OBJECT                "Ljava/lang/Object;"
 #define CLASS                 "Ljava/lang/Class;"
@@ -1300,8 +1345,10 @@
 #define HS_RESOLVED_KLASS     "Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;"
 #define HS_CONSTANT_POOL      "Ljdk/vm/ci/hotspot/HotSpotConstantPool;"
 #define HS_COMPILED_CODE      "Ljdk/vm/ci/hotspot/HotSpotCompiledCode;"
+#define HS_CONFIG             "Ljdk/vm/ci/hotspot/HotSpotVMConfig;"
 #define HS_METADATA           "Ljdk/vm/ci/hotspot/HotSpotMetaData;"
 #define HS_STACK_FRAME_REF    "Ljdk/vm/ci/hotspot/HotSpotStackFrameReference;"
+#define HS_SPECULATION_LOG    "Ljdk/vm/ci/hotspot/HotSpotSpeculationLog;"
 #define METASPACE_METHOD_DATA "J"
 
 JNINativeMethod CompilerToVM::methods[] = {
@@ -1339,12 +1386,12 @@
   {CC"getResolvedJavaMethod",                        CC"(Ljava/lang/Object;J)"HS_RESOLVED_METHOD,                                      FN_PTR(getResolvedJavaMethod)},
   {CC"getConstantPool",                              CC"(Ljava/lang/Object;J)"HS_CONSTANT_POOL,                                        FN_PTR(getConstantPool)},
   {CC"getResolvedJavaType",                          CC"(Ljava/lang/Object;JZ)"HS_RESOLVED_KLASS,                                      FN_PTR(getResolvedJavaType)},
-  {CC"initializeConfiguration",                      CC"()J",                                                                          FN_PTR(initializeConfiguration)},
-  {CC"installCode",                                  CC"("TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I",      FN_PTR(installCode)},
+  {CC"initializeConfiguration",                      CC"("HS_CONFIG")J",                                                               FN_PTR(initializeConfiguration)},
+  {CC"installCode",                                  CC"("TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE HS_SPECULATION_LOG")I",   FN_PTR(installCode)},
   {CC"getMetadata",                                  CC"("TARGET_DESCRIPTION HS_COMPILED_CODE HS_METADATA")I",                         FN_PTR(getMetadata)},
   {CC"notifyCompilationStatistics",                  CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V",                                 FN_PTR(notifyCompilationStatistics)},
   {CC"resetCompilationStatistics",                   CC"()V",                                                                          FN_PTR(resetCompilationStatistics)},
-  {CC"disassembleCodeBlob",                          CC"(J)"STRING,                                                                    FN_PTR(disassembleCodeBlob)},
+  {CC"disassembleCodeBlob",                          CC"("INSTALLED_CODE")"STRING,                                                     FN_PTR(disassembleCodeBlob)},
   {CC"executeInstalledCode",                         CC"(["OBJECT INSTALLED_CODE")"OBJECT,                                             FN_PTR(executeInstalledCode)},
   {CC"getLineNumberTable",                           CC"("HS_RESOLVED_METHOD")[J",                                                     FN_PTR(getLineNumberTable)},
   {CC"getLocalVariableTableStart",                   CC"("HS_RESOLVED_METHOD")J",                                                      FN_PTR(getLocalVariableTableStart)},
@@ -1357,11 +1404,12 @@
   {CC"isMature",                                     CC"("METASPACE_METHOD_DATA")Z",                                                   FN_PTR(isMature)},
   {CC"hasCompiledCodeForOSR",                        CC"("HS_RESOLVED_METHOD"II)Z",                                                    FN_PTR(hasCompiledCodeForOSR)},
   {CC"getSymbol",                                    CC"(J)"STRING,                                                                    FN_PTR(getSymbol)},
-  {CC"getNextStackFrame",                            CC"("HS_STACK_FRAME_REF "["HS_RESOLVED_METHOD"I)"HS_STACK_FRAME_REF,              FN_PTR(getNextStackFrame)},
+  {CC"getNextStackFrame",                            CC"("HS_STACK_FRAME_REF "["RESOLVED_METHOD"I)"HS_STACK_FRAME_REF,                 FN_PTR(getNextStackFrame)},
   {CC"materializeVirtualObjects",                    CC"("HS_STACK_FRAME_REF"Z)V",                                                     FN_PTR(materializeVirtualObjects)},
   {CC"shouldDebugNonSafepoints",                     CC"()Z",                                                                          FN_PTR(shouldDebugNonSafepoints)},
   {CC"writeDebugOutput",                             CC"([BII)V",                                                                      FN_PTR(writeDebugOutput)},
   {CC"flushDebugOutput",                             CC"()V",                                                                          FN_PTR(flushDebugOutput)},
+  {CC"methodDataProfileDataSize",                    CC"(JI)I",                                                                        FN_PTR(methodDataProfileDataSize)},
 };
 
 int CompilerToVM::methods_count() {
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -94,9 +94,11 @@
     return (MethodData*) (address) metaspaceMethodData;
   }
 
-  static oop get_jvmci_method(methodHandle method, TRAPS);
+  static oop get_jvmci_method(const methodHandle& method, TRAPS);
 
   static oop get_jvmci_type(KlassHandle klass, TRAPS);
+
+  static void invalidate_installed_code(Handle installedCode, TRAPS);
 };
 
 class JavaArgumentUnboxer : public SignatureIterator {
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,18 +64,18 @@
 // Note: the logic of this method should mirror the logic of
 // constantPoolOopDesc::verify_constant_pool_resolve.
 bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass) {
-  if (accessing_klass->oop_is_objArray()) {
+  if (accessing_klass->is_objArray_klass()) {
     accessing_klass = ObjArrayKlass::cast(accessing_klass())->bottom_klass();
   }
-  if (!accessing_klass->oop_is_instance()) {
+  if (!accessing_klass->is_instance_klass()) {
     return true;
   }
 
-  if (resolved_klass->oop_is_objArray()) {
+  if (resolved_klass->is_objArray_klass()) {
     // Find the element klass, if this is an array.
     resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
   }
-  if (resolved_klass->oop_is_instance()) {
+  if (resolved_klass->is_instance_klass()) {
     return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
   }
   return true;
@@ -83,7 +83,7 @@
 
 // ------------------------------------------------------------------
 KlassHandle JVMCIEnv::get_klass_by_name_impl(KlassHandle& accessing_klass,
-                                          constantPoolHandle& cpool,
+                                          const constantPoolHandle& cpool,
                                           Symbol* sym,
                                           bool require_local) {
   JVMCI_EXCEPTION_CONTEXT;
@@ -174,7 +174,7 @@
 
 // ------------------------------------------------------------------
 // Implementation of get_klass_by_index.
-KlassHandle JVMCIEnv::get_klass_by_index_impl(constantPoolHandle& cpool,
+KlassHandle JVMCIEnv::get_klass_by_index_impl(const constantPoolHandle& cpool,
                                         int index,
                                         bool& is_accessible,
                                         KlassHandle& accessor) {
@@ -215,7 +215,7 @@
 
 // ------------------------------------------------------------------
 // Get a klass from the constant pool.
-KlassHandle JVMCIEnv::get_klass_by_index(constantPoolHandle& cpool,
+KlassHandle JVMCIEnv::get_klass_by_index(const constantPoolHandle& cpool,
                                    int index,
                                    bool& is_accessible,
                                    KlassHandle& accessor) {
@@ -312,7 +312,7 @@
 
 
 // ------------------------------------------------------------------
-methodHandle JVMCIEnv::get_method_by_index_impl(constantPoolHandle& cpool,
+methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
                                           int index, Bytecodes::Code bc,
                                           instanceKlassHandle& accessor) {
   if (bc == Bytecodes::_invokedynamic) {
@@ -383,9 +383,9 @@
   // For the case of <array>.clone(), the method holder can be an ArrayKlass*
   // instead of an InstanceKlass*.  For that case simply pretend that the
   // declared holder is Object.clone since that's where the call will bottom out.
-  if (method_holder->oop_is_instance()) {
+  if (method_holder->is_instance_klass()) {
     return instanceKlassHandle(method_holder());
-  } else if (method_holder->oop_is_array()) {
+  } else if (method_holder->is_array_klass()) {
     return instanceKlassHandle(SystemDictionary::Object_klass());
   } else {
     ShouldNotReachHere();
@@ -395,7 +395,7 @@
 
 
 // ------------------------------------------------------------------
-methodHandle JVMCIEnv::get_method_by_index(constantPoolHandle& cpool,
+methodHandle JVMCIEnv::get_method_by_index(const constantPoolHandle& cpool,
                                      int index, Bytecodes::Code bc,
                                      instanceKlassHandle& accessor) {
   ResourceMark rm;
@@ -494,12 +494,12 @@
       MethodData* mdp = method()->method_data();
       if (mdp != NULL) {
         mdp->inc_decompile_count();
+#ifdef ASSERT
         if (mdp->decompile_count() > (uint)PerMethodRecompilationCutoff) {
-          // TODO (chaeubl) enable this in the fastdebug build only once we are more stable
           ResourceMark m;
           tty->print_cr("WARN: endless recompilation of %s. Method was set to not compilable.", method()->name_and_sig_as_C_string());
-          //ShouldNotReachHere();
         }
+#endif
       }
 
       // All buffers in the CodeBuffer are allocated in the CodeCache.
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -83,13 +83,13 @@
                              bool require_local);
 
   // Constant pool access.
-  static KlassHandle   get_klass_by_index(constantPoolHandle& cpool,
+  static KlassHandle   get_klass_by_index(const constantPoolHandle& cpool,
                                 int klass_index,
                                 bool& is_accessible,
                                 KlassHandle& loading_klass);
   static void   get_field_by_index(instanceKlassHandle& loading_klass, fieldDescriptor& fd,
                                 int field_index);
-  static methodHandle  get_method_by_index(constantPoolHandle& cpool,
+  static methodHandle  get_method_by_index(const constantPoolHandle& cpool,
                                  int method_index, Bytecodes::Code bc,
                                  instanceKlassHandle& loading_klass);
 
@@ -106,16 +106,16 @@
 
   // Implementation methods for loading and constant pool access.
   static KlassHandle get_klass_by_name_impl(KlassHandle& accessing_klass,
-                                  constantPoolHandle& cpool,
+                                  const constantPoolHandle& cpool,
                                   Symbol* klass_name,
                                   bool require_local);
-  static KlassHandle   get_klass_by_index_impl(constantPoolHandle& cpool,
+  static KlassHandle   get_klass_by_index_impl(const constantPoolHandle& cpool,
                                      int klass_index,
                                      bool& is_accessible,
                                      KlassHandle& loading_klass);
   static void   get_field_by_index_impl(instanceKlassHandle& loading_klass, fieldDescriptor& fd,
                                      int field_index);
-  static methodHandle  get_method_by_index_impl(constantPoolHandle& cpool,
+  static methodHandle  get_method_by_index_impl(const constantPoolHandle& cpool,
                                       int method_index, Bytecodes::Code bc,
                                       instanceKlassHandle& loading_klass);
 
--- a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -71,7 +71,6 @@
 
 void JVMCIJavaClasses::compute_offsets() {
   COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, OOP_FIELD, OOP_FIELD, STATIC_OOP_FIELD, STATIC_OOP_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD)
-  guarantee(InstalledCode::_address_offset == sizeof(oopDesc), "codeBlob must be first field!");
 }
 
 #define EMPTY0
--- a/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -65,6 +65,7 @@
   end_class                                                                                                                                                    \
   start_class(InstalledCode)                                                                                                                                   \
     long_field(InstalledCode, address)                                                                                                                         \
+    long_field(InstalledCode, entryPoint)                                                                                                                      \
     long_field(InstalledCode, version)                                                                                                                         \
     oop_field(InstalledCode, name, "Ljava/lang/String;")                                                                                                       \
   end_class                                                                                                                                                    \
@@ -215,8 +216,7 @@
     boolean_field(HotSpotObjectConstantImpl, compressed)                                                                                                       \
   end_class                                                                                                                                                    \
   start_class(HotSpotMetaspaceConstantImpl)                                                                                                                    \
-    long_field(HotSpotMetaspaceConstantImpl, primitive)                                                                                                        \
-    oop_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljava/lang/Object;")                                                                             \
+    oop_field(HotSpotMetaspaceConstantImpl, metaspaceObject, "Ljdk/vm/ci/hotspot/MetaspaceWrapperObject;")                                            \
     boolean_field(HotSpotMetaspaceConstantImpl, compressed)                                                                                                    \
   end_class                                                                                                                                                    \
   start_class(HotSpotSentinelConstant)                                                                                                                         \
@@ -261,11 +261,11 @@
   end_class                                                                                                                                                    \
   start_class(StackLockValue)                                                                                                                                  \
     oop_field(StackLockValue, owner, "Ljdk/vm/ci/meta/JavaValue;")                                                                                             \
-    oop_field(StackLockValue, slot, "Ljdk/vm/ci/code/StackSlotValue;")                                                                                         \
+    oop_field(StackLockValue, slot, "Ljdk/vm/ci/meta/AllocatableValue;")                                                                                       \
     boolean_field(StackLockValue, eliminated)                                                                                                                  \
   end_class                                                                                                                                                    \
-  start_class(SpeculationLog)                                                                                                                                  \
-    oop_field(SpeculationLog, lastFailed, "Ljava/lang/Object;")                                                                                                \
+  start_class(HotSpotSpeculationLog)                                                                                                                           \
+    oop_field(HotSpotSpeculationLog, lastFailed, "Ljava/lang/Object;")                                                                                         \
   end_class                                                                                                                                                    \
   start_class(HotSpotStackFrameReference)                                                                                                                      \
     oop_field(HotSpotStackFrameReference, compilerToVM, "Ljdk/vm/ci/hotspot/CompilerToVM;")                                                                    \
@@ -292,9 +292,11 @@
   start_class(HotSpotConstantPool)                                                                                                                             \
     long_field(HotSpotConstantPool, metaspaceConstantPool)                                                                                                     \
   end_class                                                                                                                                                    \
+  start_class(HotSpotJVMCIRuntime)                                                                                                                             \
+  objArrayOop_field(HotSpotJVMCIRuntime, trivialPrefixes, "[Ljava/lang/String;")                                                                               \
+  end_class                                                                                                                                                    \
   /* end*/
 
-
 #define START_CLASS(name)                                                                                                                                      \
 class name : AllStatic {                                                                                                                                       \
   private:                                                                                                                                                     \
@@ -306,7 +308,7 @@
     }                                                                                                                                                          \
     static void compute_offsets();                                                                                                                             \
   public:                                                                                                                                                      \
-    static InstanceKlass* klass() { return SystemDictionary::name##_klass() == NULL ? NULL : InstanceKlass::cast(SystemDictionary::name##_klass()); }
+    static InstanceKlass* klass() { return SystemDictionary::name##_klass(); }
 
 #define END_CLASS };
 
--- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -52,6 +52,8 @@
 const char* JVMCIRuntime::_compiler = NULL;
 int JVMCIRuntime::_options_count = 0;
 SystemProperty** JVMCIRuntime::_options = NULL;
+int JVMCIRuntime::_trivial_prefixes_count = 0;
+char** JVMCIRuntime::_trivial_prefixes = NULL;
 bool JVMCIRuntime::_shutdown_called = false;
 
 static const char* OPTION_PREFIX = "jvmci.option.";
@@ -124,7 +126,7 @@
   //       (This may have to change if this code changes!)
   assert(array_klass->is_klass(), "not a class");
   oop obj;
-  if (array_klass->oop_is_typeArray()) {
+  if (array_klass->is_typeArray_klass()) {
     BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type();
     obj = oopFactory::new_typeArray(elt_type, length, CHECK);
   } else {
@@ -433,12 +435,13 @@
   }
 JRT_END
 
-JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, jint flags))
-  bool string =  mask_bits_are_true(flags, LOG_OBJECT_STRING);
-  bool addr = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS);
-  bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE);
-  if (!string) {
-    if (!addr && obj->is_oop_or_null(true)) {
+JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, bool as_string, bool newline))
+  ttyLocker ttyl;
+
+  if (obj == NULL) {
+    tty->print("NULL");
+  } else if (obj->is_oop_or_null(true) && (!as_string || !java_lang_String::is_instance(obj))) {
+    if (obj->is_oop_or_null(true)) {
       char buf[O_BUFLEN];
       tty->print("%s@" INTPTR_FORMAT, obj->klass()->name()->as_C_string(buf, O_BUFLEN), p2i(obj));
     } else {
@@ -628,10 +631,10 @@
 
 static bool jvmci_options_file_exists() {
   const char* home = Arguments::get_java_home();
-  size_t path_len = strlen(home) + strlen("/lib/jvmci/options") + 1;
+  size_t path_len = strlen(home) + strlen("/lib/jvmci.options") + 1;
   char path[JVM_MAXPATHLEN];
   char sep = os::file_separator()[0];
-  jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cjvmci%coptions", home, sep, sep, sep);
+  jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cjvmci.options", home, sep, sep);
   struct stat st;
   return os::stat(path, &st) == 0;
 }
@@ -656,7 +659,8 @@
         for (int i = 0; i < _options_count; i++) {
           SystemProperty* prop = _options[i];
           oop name = java_lang_String::create_oop_from_str(prop->key() + OPTION_PREFIX_LEN, CHECK);
-          oop value = java_lang_String::create_oop_from_str(prop->value(), CHECK);
+          const char* prop_value = prop->value() != NULL ? prop->value() : "";
+          oop value = java_lang_String::create_oop_from_str(prop_value, CHECK);
           options->obj_at_put(i * 2, name);
           options->obj_at_put((i * 2) + 1, value);
         }
@@ -682,6 +686,20 @@
     Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime",
                                "runtime",
                                "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK);
+    objArrayOop trivial_prefixes = HotSpotJVMCIRuntime::trivialPrefixes(result);
+    if (trivial_prefixes != NULL) {
+      char** prefixes = NEW_C_HEAP_ARRAY(char*, trivial_prefixes->length(), mtCompiler);
+      for (int i = 0; i < trivial_prefixes->length(); i++) {
+        oop str = trivial_prefixes->obj_at(i);
+        if (str == NULL) {
+          THROW(vmSymbols::java_lang_NullPointerException());
+        } else {
+          prefixes[i] = strdup(java_lang_String::as_utf8_string(str));
+        }
+      }
+      _trivial_prefixes = prefixes;
+      _trivial_prefixes_count = trivial_prefixes->length();
+    }
     _HotSpotJVMCIRuntime_initialized = true;
     _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result());
   }
@@ -877,15 +895,27 @@
   _compiler = compiler;
 }
 
-jint JVMCIRuntime::save_options(SystemProperty* props) {
+void JVMCIRuntime::maybe_print_flags(TRAPS) {
+  if (_options != NULL) {
+    for (int i = 0; i < _options_count; i++) {
+      SystemProperty* p = _options[i];
+      const char* name = p->key() + OPTION_PREFIX_LEN;
+      if (strcmp(name, "PrintFlags") == 0 || strcmp(name, "ShowFlags") == 0) {
+        JVMCIRuntime::initialize_well_known_classes(CHECK);
+        HandleMark hm;
+        ResourceMark rm;
+        JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK);
+        return;
+      }
+    }
+  }
+}
+
+void JVMCIRuntime::save_options(SystemProperty* props) {
   int count = 0;
   SystemProperty* first = NULL;
   for (SystemProperty* p = props; p != NULL; p = p->next()) {
     if (strncmp(p->key(), OPTION_PREFIX, OPTION_PREFIX_LEN) == 0) {
-      if (p->value() == NULL || strlen(p->value()) == 0) {
-        jio_fprintf(defaultStream::output_stream(), "JVMCI option %s must have non-zero length value\n", p->key());
-        return JNI_ERR;
-      }
       if (first == NULL) {
         first = p;
       }
@@ -905,7 +935,6 @@
     }
     assert (insert_pos - _options == count, "must be");
   }
-  return JNI_OK;
 }
 
 void JVMCIRuntime::shutdown() {
@@ -921,6 +950,20 @@
   }
 }
 
+bool JVMCIRuntime::treat_as_trivial(Method* method) {
+  if (_HotSpotJVMCIRuntime_initialized) {
+    oop loader = method->method_holder()->class_loader();
+    if (loader == NULL) {
+      for (int i = 0; i < _trivial_prefixes_count; i++) {
+        if (method->method_holder()->name()->starts_with(_trivial_prefixes[i])) {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
 void JVMCIRuntime::call_printStackTrace(Handle exception, Thread* thread) {
   assert(exception->is_a(SystemDictionary::Throwable_klass()), "Throwable instance expected");
   JavaValue result(T_VOID);
@@ -949,18 +992,18 @@
 
 void JVMCIRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) {
   struct stat st;
-  if (os::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file
-    int file_handle = os::open(path, 0, 0);
+  if (::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file
+    int file_handle = ::open(path, os::default_file_open_flags(), 0);
     if (file_handle != -1) {
       char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal);
       int num_read;
-      num_read = (int) os::read(file_handle, (char*) buffer, st.st_size);
+      num_read = (int) ::read(file_handle, (char*) buffer, st.st_size);
       if (num_read == -1) {
         warning("Error reading file %s due to %s", path, strerror(errno));
       } else if (num_read != st.st_size) {
         warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path);
       }
-      os::close(file_handle);
+      ::close(file_handle);
       closure->set_filename(path);
       if (num_read == st.st_size) {
         buffer[num_read] = '\0';
--- a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -54,24 +54,6 @@
   void set_filename(char* path) {_filename = path; _lineNo = 0;}
 };
 
-#define CHECK_ABORT THREAD); \
-  if (HAS_PENDING_EXCEPTION) { \
-    char buf[256]; \
-    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
-    JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
-    return; \
-  } \
-  (void)(0
-
-#define CHECK_ABORT_(result) THREAD); \
-  if (HAS_PENDING_EXCEPTION) { \
-    char buf[256]; \
-    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
-    JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
-    return result; \
-  } \
-  (void)(0
-
 class JVMCIRuntime: public AllStatic {
  private:
   static jobject _HotSpotJVMCIRuntime_instance;
@@ -81,6 +63,9 @@
   static int _options_count;
   static SystemProperty** _options;
 
+  static int _trivial_prefixes_count;
+  static char** _trivial_prefixes;
+
   static bool _shutdown_called;
 
   /**
@@ -108,9 +93,14 @@
    * when JVMCI is initialized.
    *
    * @param props the head of the system property list
-   * @return JNI_ERR if a JVMCI option has a zero length value, JNI_OK otherwise
    */
-  static jint save_options(SystemProperty* props);
+  static void save_options(SystemProperty* props);
+
+  /**
+   * If either the PrintFlags or ShowFlags JVMCI option is present,
+   * then JVMCI is initialized to show the help message.
+   */
+  static void maybe_print_flags(TRAPS);
 
   static bool is_HotSpotJVMCIRuntime_initialized() { return _HotSpotJVMCIRuntime_initialized; }
 
@@ -150,6 +140,7 @@
     return _shutdown_called;
   }
 
+  static bool treat_as_trivial(Method* method);
   static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure);
 
   /**
@@ -162,6 +153,24 @@
    */
   static void call_printStackTrace(Handle exception, Thread* thread);
 
+#define CHECK_ABORT THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
+    return; \
+  } \
+  (void)(0
+
+#define CHECK_ABORT_(result) THREAD); \
+  if (HAS_PENDING_EXCEPTION) { \
+    char buf[256]; \
+    jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \
+    JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \
+    return result; \
+  } \
+  (void)(0
+
   static BasicType kindToBasicType(jchar ch);
 
   // The following routines are all called from compiled JVMCI code
@@ -183,13 +192,11 @@
   static oopDesc* load_and_clear_exception(JavaThread* thread);
   static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3);
   static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline);
-  // Note: Must be kept in sync with constants in com.oracle.graal.replacements.Log
-  enum {
-    LOG_OBJECT_NEWLINE = 0x01,
-    LOG_OBJECT_STRING  = 0x02,
-    LOG_OBJECT_ADDRESS = 0x04
-  };
-  static void log_object(JavaThread* thread, oopDesc* msg, jint flags);
+  // Print the passed in object, optionally followed by a newline.  If
+  // as_string is true and the object is a java.lang.String then it
+  // printed as a string, otherwise the type of the object is printed
+  // followed by its address.
+  static void log_object(JavaThread* thread, oopDesc* object, bool as_string, bool newline);
   static void write_barrier_pre(JavaThread* thread, oopDesc* obj);
   static void write_barrier_post(JavaThread* thread, void* card);
   static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);
--- a/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -47,6 +47,8 @@
   do_klass(HotSpotOopMap_klass,                          jdk_vm_ci_hotspot_HotSpotOopMap,                       Jvmci) \
   do_klass(HotSpotConstantPool_klass,                    jdk_vm_ci_hotspot_HotSpotConstantPool,                 Jvmci) \
   do_klass(HotSpotJVMCIMetaAccessContext_klass,          jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext,       Jvmci) \
+  do_klass(HotSpotJVMCIRuntime_klass,                    jdk_vm_ci_hotspot_HotSpotJVMCIRuntime,                 Jvmci) \
+  do_klass(HotSpotSpeculationLog_klass,                  jdk_vm_ci_hotspot_HotSpotSpeculationLog,               Jvmci) \
   do_klass(Assumptions_ConcreteMethod_klass,             jdk_vm_ci_meta_Assumptions_ConcreteMethod,             Jvmci) \
   do_klass(Assumptions_NoFinalizableSubclass_klass,      jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass,      Jvmci) \
   do_klass(Assumptions_ConcreteSubtype_klass,            jdk_vm_ci_meta_Assumptions_ConcreteSubtype,            Jvmci) \
@@ -74,7 +76,6 @@
   do_klass(StackSlot_klass,                              jdk_vm_ci_code_StackSlot,                              Jvmci) \
   do_klass(StackLockValue_klass,                         jdk_vm_ci_code_StackLockValue,                         Jvmci) \
   do_klass(VirtualObject_klass,                          jdk_vm_ci_code_VirtualObject,                          Jvmci) \
-  do_klass(SpeculationLog_klass,                         jdk_vm_ci_meta_SpeculationLog,                         Jvmci) \
   do_klass(JavaConstant_klass,                           jdk_vm_ci_meta_JavaConstant,                           Jvmci) \
   do_klass(PrimitiveConstant_klass,                      jdk_vm_ci_meta_PrimitiveConstant,                      Jvmci) \
   do_klass(RawConstant_klass,                            jdk_vm_ci_meta_RawConstant,                            Jvmci) \
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -70,6 +70,20 @@
   declare_constant(CompilerToVM::KLASS_TAG)                                                       \
   declare_constant(CompilerToVM::SYMBOL_TAG)                                                      \
                                                                                                   \
+  declare_constant(BitData::exception_seen_flag)                                                  \
+  declare_constant(BitData::null_seen_flag)                                                       \
+  declare_constant(CounterData::count_off)                                                        \
+  declare_constant(JumpData::taken_off_set)                                                       \
+  declare_constant(JumpData::displacement_off_set)                                                \
+  declare_constant(ReceiverTypeData::nonprofiled_count_off_set)                                   \
+  declare_constant(ReceiverTypeData::receiver_type_row_cell_count)                                \
+  declare_constant(ReceiverTypeData::receiver0_offset)                                            \
+  declare_constant(ReceiverTypeData::count0_offset)                                               \
+  declare_constant(BranchData::not_taken_off_set)                                                 \
+  declare_constant(ArrayData::array_len_off_set)                                                  \
+  declare_constant(ArrayData::array_start_off_set)                                                \
+  declare_constant(MultiBranchData::per_case_cell_count)                                          \
+                                                                                                  \
   declare_constant(CodeInstaller::VERIFIED_ENTRY)                                                 \
   declare_constant(CodeInstaller::UNVERIFIED_ENTRY)                                               \
   declare_constant(CodeInstaller::OSR_ENTRY)                                                      \
@@ -84,6 +98,7 @@
   declare_constant(CodeInstaller::POLL_RETURN_NEAR)                                               \
   declare_constant(CodeInstaller::POLL_FAR)                                                       \
   declare_constant(CodeInstaller::POLL_RETURN_FAR)                                                \
+  declare_constant(CodeInstaller::CARD_TABLE_SHIFT)                                               \
   declare_constant(CodeInstaller::CARD_TABLE_ADDRESS)                                             \
   declare_constant(CodeInstaller::HEAP_TOP_ADDRESS)                                               \
   declare_constant(CodeInstaller::HEAP_END_ADDRESS)                                               \
--- a/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -48,6 +48,8 @@
   template(jdk_vm_ci_hotspot_HotSpotOopMap,                       "jdk/vm/ci/hotspot/HotSpotOopMap")                       \
   template(jdk_vm_ci_hotspot_HotSpotConstantPool,                 "jdk/vm/ci/hotspot/HotSpotConstantPool")                 \
   template(jdk_vm_ci_hotspot_HotSpotJVMCIMetaAccessContext,       "jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext")       \
+  template(jdk_vm_ci_hotspot_HotSpotJVMCIRuntime,                 "jdk/vm/ci/hotspot/HotSpotJVMCIRuntime")                 \
+  template(jdk_vm_ci_hotspot_HotSpotSpeculationLog,               "jdk/vm/ci/hotspot/HotSpotSpeculationLog")               \
   template(jdk_vm_ci_meta_JavaConstant,                           "jdk/vm/ci/meta/JavaConstant")                           \
   template(jdk_vm_ci_meta_PrimitiveConstant,                      "jdk/vm/ci/meta/PrimitiveConstant")                      \
   template(jdk_vm_ci_meta_RawConstant,                            "jdk/vm/ci/meta/RawConstant")                            \
@@ -61,7 +63,6 @@
   template(jdk_vm_ci_meta_Assumptions_NoFinalizableSubclass,      "jdk/vm/ci/meta/Assumptions$NoFinalizableSubclass")      \
   template(jdk_vm_ci_meta_Assumptions_ConcreteMethod,             "jdk/vm/ci/meta/Assumptions$ConcreteMethod")             \
   template(jdk_vm_ci_meta_Assumptions_CallSiteTargetValue,        "jdk/vm/ci/meta/Assumptions$CallSiteTargetValue")        \
-  template(jdk_vm_ci_meta_SpeculationLog,                         "jdk/vm/ci/meta/SpeculationLog")                         \
   template(jdk_vm_ci_code_Architecture,                           "jdk/vm/ci/code/Architecture")                           \
   template(jdk_vm_ci_code_TargetDescription,                      "jdk/vm/ci/code/TargetDescription")                      \
   template(jdk_vm_ci_code_CompilationResult_Call,                 "jdk/vm/ci/code/CompilationResult$Call")                 \
--- a/hotspot/src/share/vm/memory/allocation.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/memory/allocation.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -66,7 +66,7 @@
 }
 
 void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flags) throw() {
-  address res;
+  address res = NULL;
   switch (type) {
    case C_HEAP:
     res = (address)AllocateHeap(size, flags, CALLER_PC);
@@ -88,8 +88,8 @@
 
 void* ResourceObj::operator new(size_t size, const std::nothrow_t&  nothrow_constant,
     allocation_type type, MEMFLAGS flags) throw() {
-  //should only call this with std::nothrow, use other operator new() otherwise
-  address res;
+  // should only call this with std::nothrow, use other operator new() otherwise
+  address res = NULL;
   switch (type) {
    case C_HEAP:
     res = (address)AllocateHeap(size, flags, CALLER_PC, AllocFailStrategy::RETURN_NULL);
--- a/hotspot/src/share/vm/memory/filemap.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/memory/filemap.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -168,6 +168,7 @@
   _version = _current_version;
   _alignment = alignment;
   _obj_alignment = ObjectAlignmentInBytes;
+  _compact_strings = CompactStrings;
   _narrow_oop_mode = Universe::narrow_oop_mode();
   _narrow_oop_shift = Universe::narrow_oop_shift();
   _max_heap_size = MaxHeapSize;
@@ -900,6 +901,13 @@
                   _obj_alignment, ObjectAlignmentInBytes);
     return false;
   }
+  if (_compact_strings != CompactStrings) {
+    FileMapInfo::fail_continue("The shared archive file's CompactStrings setting (%s)"
+                  " does not equal the current CompactStrings setting (%s).",
+                  _compact_strings ? "enabled" : "disabled",
+                  CompactStrings   ? "enabled" : "disabled");
+    return false;
+  }
 
   return true;
 }
--- a/hotspot/src/share/vm/memory/filemap.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/memory/filemap.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -95,6 +95,7 @@
     size_t _alignment;                // how shared archive should be aligned
     int    _obj_alignment;            // value of ObjectAlignmentInBytes
     int    _narrow_oop_shift;         // compressed oop encoding shift
+    bool   _compact_strings;          // value of CompactStrings
     uintx  _max_heap_size;            // java max heap size during dumping
     Universe::NARROW_OOP_MODE _narrow_oop_mode; // compressed oop encoding mode
     int     _narrow_klass_shift;      // save narrow klass base and shift
--- a/hotspot/src/share/vm/memory/heapInspection.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/memory/heapInspection.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -286,7 +286,6 @@
   return true;
 }
 
-PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
 void KlassInfoHisto::print_title(outputStream* st, bool csv_format,
                                  bool selected[], int width_table[],
                                  const char *name_table[]) {
@@ -298,11 +297,10 @@
     st->print(",ClassName");
   } else {
     st->print("Index Super");
-    for (int c=0; c<KlassSizeStats::_num_columns; c++) {
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-      if (selected[c]) {st->print(str_fmt(width_table[c]), name_table[c]);}
-PRAGMA_DIAG_POP
+    for (int c = 0; c < KlassSizeStats::_num_columns; c++) {
+      if (selected[c]) {
+        st->print("%*s", width_table[c], name_table[c]);
+      }
     }
     st->print(" ClassName");
   }
@@ -321,7 +319,7 @@
 
   void do_cinfo(KlassInfoEntry* cie) {
     // ignore array classes
-    if (cie->klass()->oop_is_instance()) {
+    if (cie->klass()->is_instance_klass()) {
       _elements->append(cie);
     }
   }
@@ -348,8 +346,7 @@
 
   for(int i = 0; i < elements.length(); i++) {
     KlassInfoEntry* cie = elements.at(i);
-    const InstanceKlass* k = (InstanceKlass*)cie->klass();
-    Klass* super = ((InstanceKlass*)k)->java_super();
+    Klass* super = cie->klass()->super();
 
     // Set the index for the class.
     cie->set_index(i + 1);
@@ -544,8 +541,8 @@
       } else {
         int super_index = -1;
         // Print the stats for this class.
-        if (k->oop_is_instance()) {
-          Klass* super = ((InstanceKlass*)k)->java_super();
+        if (k->is_instance_klass()) {
+          Klass* super = k->super();
           if (super) {
             KlassInfoEntry* super_e = _cit->lookup(super);
             if (super_e) {
@@ -608,18 +605,12 @@
           case KlassSizeStats::_index_inst_size:
           case KlassSizeStats::_index_inst_count:
           case KlassSizeStats::_index_method_count:
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-            st->print(str_fmt(width_table[c]), "-");
-PRAGMA_DIAG_POP
+            st->print("%*s", width_table[c], "-");
             break;
           default:
             {
               double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes;
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-              st->print(perc_fmt(width_table[c]), perc);
-PRAGMA_DIAG_POP
+              st->print("%*.1f%%", width_table[c]-1, perc);
             }
           }
         }
--- a/hotspot/src/share/vm/memory/heapInspection.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/memory/heapInspection.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -313,32 +313,13 @@
     return HeapWordSize * x->size();
   }
 
-  // returns a format string to print a julong with the given width. E.g,
-  // printf(num_fmt(6), julong(10)) would print out the number 10 with 4
-  // leading spaces.
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED
-
   static void print_julong(outputStream* st, int width, julong n) {
     int num_spaces = width - julong_width(n);
     if (num_spaces > 0) {
-      st->print(str_fmt(num_spaces), "");
+      st->print("%*s", num_spaces, "");
     }
     st->print(JULONG_FORMAT, n);
   }
-PRAGMA_DIAG_POP
-
-  static char* perc_fmt(int width) {
-    static char buf[32];
-    jio_snprintf(buf, sizeof(buf), "%%%d.1f%%%%", width-1);
-    return buf;
-  }
-
-  static char* str_fmt(int width) {
-    static char buf[32];
-    jio_snprintf(buf, sizeof(buf), "%%%ds", width);
-    return buf;
-  }
 
   static int julong_width(julong n) {
     if (n == 0) {
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -90,7 +90,7 @@
 static GrowableArray<Klass*>* _global_klass_objects;
 static void collect_classes(Klass* k) {
   _global_klass_objects->append_if_missing(k);
-  if (k->oop_is_instance()) {
+  if (k->is_instance_klass()) {
     // Add in the array classes too
     InstanceKlass* ik = InstanceKlass::cast(k);
     ik->array_klasses_do(collect_classes);
@@ -126,7 +126,7 @@
 static void rewrite_nofast_bytecodes_and_calculate_fingerprints() {
   for (int i = 0; i < _global_klass_objects->length(); i++) {
     Klass* k = _global_klass_objects->at(i);
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       InstanceKlass* ik = InstanceKlass::cast(k);
       for (int i = 0; i < ik->methods()->length(); i++) {
         Method* m = ik->methods()->at(i);
@@ -199,9 +199,9 @@
   int n = _global_klass_objects->length();
   for (int i = 0; i < n; i++) {
     Klass* obj = _global_klass_objects->at(i);
-    // Note oop_is_instance() is a virtual call.  After patching vtables
+    // Note is_instance_klass() is a virtual call in debug.  After patching vtables
     // all virtual calls on the dummy vtables will restore the original!
-    if (obj->oop_is_instance()) {
+    if (obj->is_instance_klass()) {
       InstanceKlass* ik = InstanceKlass::cast(obj);
       *(void**)ik = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, ik);
       ConstantPool* cp = ik->constants();
@@ -482,12 +482,12 @@
     int num_type_array = 0, num_obj_array = 0, num_inst = 0;
     for (int i = 0; i < _global_klass_objects->length(); i++) {
       Klass* k = _global_klass_objects->at(i);
-      if (k->oop_is_instance()) {
+      if (k->is_instance_klass()) {
         num_inst ++;
-      } else if (k->oop_is_objArray()) {
+      } else if (k->is_objArray_klass()) {
         num_obj_array ++;
       } else {
-        assert(k->oop_is_typeArray(), "sanity");
+        assert(k->is_typeArray_klass(), "sanity");
         num_type_array ++;
       }
     }
@@ -540,7 +540,7 @@
 
   NOT_PRODUCT(SystemDictionary::verify();)
 
-  // Copy the the symbol table, string table, and the system dictionary to the shared
+  // Copy the symbol table, string table, and the system dictionary to the shared
   // space in usable form.  Copy the hashtable
   // buckets first [read-write], then copy the linked lists of entries
   // [read-only].
@@ -679,8 +679,8 @@
 
 void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) {
   Klass* k = obj;
-  if (k->oop_is_instance()) {
-    InstanceKlass* ik = (InstanceKlass*) k;
+  if (k->is_instance_klass()) {
+    InstanceKlass* ik = InstanceKlass::cast(k);
     // Link the class to cause the bytecodes to be rewritten and the
     // cpcache to be created. Class verification is done according
     // to -Xverify setting.
@@ -690,7 +690,7 @@
 }
 
 void MetaspaceShared::check_one_shared_class(Klass* k) {
-  if (k->oop_is_instance() && InstanceKlass::cast(k)->check_sharing_error_state()) {
+  if (k->is_instance_klass() && InstanceKlass::cast(k)->check_sharing_error_state()) {
     _check_classes_made_progress = true;
   }
 }
--- a/hotspot/src/share/vm/memory/oopFactory.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/memory/oopFactory.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -81,10 +81,9 @@
 
 objArrayOop oopFactory::new_objArray(Klass* klass, int length, TRAPS) {
   assert(klass->is_klass(), "must be instance class");
-  if (klass->oop_is_array()) {
-    return ((ArrayKlass*)klass)->allocate_arrayArray(1, length, THREAD);
+  if (klass->is_array_klass()) {
+    return ArrayKlass::cast(klass)->allocate_arrayArray(1, length, THREAD);
   } else {
-    assert (klass->oop_is_instance(), "new object array with klass not an InstanceKlass");
-    return ((InstanceKlass*)klass)->allocate_objArray(1, length, THREAD);
+    return InstanceKlass::cast(klass)->allocate_objArray(1, length, THREAD);
   }
 }
--- a/hotspot/src/share/vm/memory/universe.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/memory/universe.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -409,7 +409,7 @@
     int i = 0;
     while (i < size) {
         // Allocate dummy in old generation
-      oop dummy = InstanceKlass::cast(SystemDictionary::Object_klass())->allocate_instance(CHECK);
+      oop dummy = SystemDictionary::Object_klass()->allocate_instance(CHECK);
       dummy_array->obj_at_put(i++, dummy);
     }
     {
@@ -484,8 +484,8 @@
     _mirrors[T_LONG]    = _long_mirror;
     _mirrors[T_SHORT]   = _short_mirror;
     _mirrors[T_VOID]    = _void_mirror;
-  //_mirrors[T_OBJECT]  = InstanceKlass::cast(_object_klass)->java_mirror();
-  //_mirrors[T_ARRAY]   = InstanceKlass::cast(_object_klass)->java_mirror();
+  //_mirrors[T_OBJECT]  = _object_klass->java_mirror();
+  //_mirrors[T_ARRAY]   = _object_klass->java_mirror();
 }
 
 void Universe::fixup_mirrors(TRAPS) {
@@ -545,9 +545,8 @@
   Klass* ko = k_h();
   klassVtable* vt = ko->vtable();
   if (vt) vt->initialize_vtable(false, CHECK);
-  if (ko->oop_is_instance()) {
-    InstanceKlass* ik = (InstanceKlass*)ko;
-    for (KlassHandle s_h(THREAD, ik->subklass());
+  if (ko->is_instance_klass()) {
+    for (KlassHandle s_h(THREAD, ko->subklass());
          s_h() != NULL;
          s_h = KlassHandle(THREAD, s_h()->next_sibling())) {
       reinitialize_vtable_of(s_h, CHECK);
@@ -998,8 +997,8 @@
   // Setup static method for registering finalizers
   // The finalizer klass must be linked before looking up the method, in
   // case it needs to get rewritten.
-  InstanceKlass::cast(SystemDictionary::Finalizer_klass())->link_class(CHECK_false);
-  Method* m = InstanceKlass::cast(SystemDictionary::Finalizer_klass())->find_method(
+  SystemDictionary::Finalizer_klass()->link_class(CHECK_false);
+  Method* m = SystemDictionary::Finalizer_klass()->find_method(
                                   vmSymbols::register_method_name(),
                                   vmSymbols::register_method_signature());
   if (m == NULL || !m->is_static()) {
@@ -1009,8 +1008,8 @@
   Universe::_finalizer_register_cache->init(
     SystemDictionary::Finalizer_klass(), m);
 
-  InstanceKlass::cast(SystemDictionary::misc_Unsafe_klass())->link_class(CHECK_false);
-  m = InstanceKlass::cast(SystemDictionary::misc_Unsafe_klass())->find_method(
+  SystemDictionary::internal_Unsafe_klass()->link_class(CHECK_false);
+  m = SystemDictionary::internal_Unsafe_klass()->find_method(
                                   vmSymbols::throwIllegalAccessError_name(),
                                   vmSymbols::void_method_signature());
   if (m != NULL && !m->is_static()) {
@@ -1020,11 +1019,11 @@
     return false; // initialization failed (cannot throw exception yet)
   }
   Universe::_throw_illegal_access_error_cache->init(
-    SystemDictionary::misc_Unsafe_klass(), m);
+    SystemDictionary::internal_Unsafe_klass(), m);
 
   // Setup method for registering loaded classes in class loader vector
-  InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false);
-  m = InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
+  SystemDictionary::ClassLoader_klass()->link_class(CHECK_false);
+  m = SystemDictionary::ClassLoader_klass()->find_method(vmSymbols::addClass_name(), vmSymbols::class_void_signature());
   if (m == NULL || m->is_static()) {
     tty->print_cr("Unable to link/verify ClassLoader.addClass method");
     return false; // initialization failed (cannot throw exception yet)
@@ -1033,8 +1032,8 @@
     SystemDictionary::ClassLoader_klass(), m);
 
   // Setup method for checking protection domain
-  InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass())->link_class(CHECK_false);
-  m = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass())->
+  SystemDictionary::ProtectionDomain_klass()->link_class(CHECK_false);
+  m = SystemDictionary::ProtectionDomain_klass()->
             find_method(vmSymbols::impliesCreateAccessControlContext_name(),
                         vmSymbols::void_boolean_signature());
   // Allow NULL which should only happen with bootstrapping.
--- a/hotspot/src/share/vm/oops/arrayKlass.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/arrayKlass.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -50,7 +50,7 @@
 
  public:
   // Testing operation
-  bool oop_is_array_slow() const { return true; }
+  DEBUG_ONLY(bool is_array_klass_slow() const { return true; })
 
   // Instance variables
   int dimension() const                 { return _dimension;      }
@@ -86,8 +86,8 @@
 
   // Casting from Klass*
   static ArrayKlass* cast(Klass* k) {
-    assert(k->oop_is_array(), "cast to ArrayKlass");
-    return (ArrayKlass*) k;
+    assert(k->is_array_klass(), "cast to ArrayKlass");
+    return static_cast<ArrayKlass*>(k);
   }
 
   GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -178,7 +178,7 @@
   return (i < 0) ? _no_index_sentinel : i;
 }
 
-void ConstantPool::trace_class_resolution(constantPoolHandle this_cp, KlassHandle k) {
+void ConstantPool::trace_class_resolution(const constantPoolHandle& this_cp, KlassHandle k) {
   ResourceMark rm;
   int line_number = -1;
   const char * source_file = NULL;
@@ -198,16 +198,16 @@
     if (source_file != NULL) {
       tty->print("RESOLVE %s %s %s:%d\n",
                  this_cp->pool_holder()->external_name(),
-                 InstanceKlass::cast(k())->external_name(), source_file, line_number);
+                 k->external_name(), source_file, line_number);
     } else {
       tty->print("RESOLVE %s %s\n",
                  this_cp->pool_holder()->external_name(),
-                 InstanceKlass::cast(k())->external_name());
+                 k->external_name());
     }
   }
 }
 
-Klass* ConstantPool::klass_at_impl(constantPoolHandle this_cp, int which,
+Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which,
                                    bool save_resolution_error, TRAPS) {
   assert(THREAD->is_Java_thread(), "must be a Java thread");
 
@@ -269,7 +269,7 @@
   ClassLoaderData* this_key = this_cp->pool_holder()->class_loader_data();
   this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
 
-  if (TraceClassResolution && !k->oop_is_array()) {
+  if (TraceClassResolution && !k->is_array_klass()) {
     // skip resolving the constant pool so that this code gets
     // called the next time some bytecodes refer to this class.
     trace_class_resolution(this_cp, k);
@@ -288,7 +288,7 @@
 // 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_cp, int which) {
+Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int which) {
   CPSlot entry = this_cp->slot_at(which);
   if (entry.is_resolved()) {
     assert(entry.get_klass()->is_klass(), "must be");
@@ -321,12 +321,12 @@
 }
 
 
-Klass* ConstantPool::klass_ref_at_if_loaded(constantPoolHandle this_cp, int which) {
+Klass* ConstantPool::klass_ref_at_if_loaded(const constantPoolHandle& this_cp, int which) {
   return klass_at_if_loaded(this_cp, this_cp->klass_ref_index_at(which));
 }
 
 
-Method* ConstantPool::method_at_if_loaded(constantPoolHandle cpool,
+Method* ConstantPool::method_at_if_loaded(const constantPoolHandle& cpool,
                                                    int which) {
   if (cpool->cache() == NULL)  return NULL;  // nothing to load yet
   int cache_index = decode_cpcache_index(which, true);
@@ -342,14 +342,14 @@
 }
 
 
-bool ConstantPool::has_appendix_at_if_loaded(constantPoolHandle cpool, int which) {
+bool ConstantPool::has_appendix_at_if_loaded(const constantPoolHandle& cpool, int which) {
   if (cpool->cache() == NULL)  return false;  // nothing to load yet
   int cache_index = decode_cpcache_index(which, true);
   ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index);
   return e->has_appendix();
 }
 
-oop ConstantPool::appendix_at_if_loaded(constantPoolHandle cpool, int which) {
+oop ConstantPool::appendix_at_if_loaded(const constantPoolHandle& cpool, int which) {
   if (cpool->cache() == NULL)  return NULL;  // nothing to load yet
   int cache_index = decode_cpcache_index(which, true);
   ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index);
@@ -357,14 +357,14 @@
 }
 
 
-bool ConstantPool::has_method_type_at_if_loaded(constantPoolHandle cpool, int which) {
+bool ConstantPool::has_method_type_at_if_loaded(const constantPoolHandle& cpool, int which) {
   if (cpool->cache() == NULL)  return false;  // nothing to load yet
   int cache_index = decode_cpcache_index(which, true);
   ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index);
   return e->has_method_type();
 }
 
-oop ConstantPool::method_type_at_if_loaded(constantPoolHandle cpool, int which) {
+oop ConstantPool::method_type_at_if_loaded(const constantPoolHandle& cpool, int which) {
   if (cpool->cache() == NULL)  return NULL;  // nothing to load yet
   int cache_index = decode_cpcache_index(which, true);
   ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index);
@@ -434,15 +434,15 @@
 }
 
 
-void ConstantPool::verify_constant_pool_resolve(constantPoolHandle this_cp, KlassHandle k, TRAPS) {
- if (k->oop_is_instance() || k->oop_is_objArray()) {
+void ConstantPool::verify_constant_pool_resolve(const constantPoolHandle& this_cp, KlassHandle k, TRAPS) {
+ if (k->is_instance_klass() || k->is_objArray_klass()) {
     instanceKlassHandle holder (THREAD, this_cp->pool_holder());
-    Klass* elem = k->oop_is_instance() ? k() : ObjArrayKlass::cast(k())->bottom_klass();
+    Klass* elem = k->is_instance_klass() ? 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
-    if (element->oop_is_instance()) {
+    if (element->is_instance_klass()) {
       LinkResolver::check_klass_accessability(holder, element, CHECK);
     }
   }
@@ -502,7 +502,7 @@
 }
 
 
-void ConstantPool::resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS) {
+void ConstantPool::resolve_string_constants_impl(const 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);
@@ -526,7 +526,7 @@
   return true;
 }
 
-Symbol* ConstantPool::exception_message(constantPoolHandle this_cp, int which, constantTag tag, oop pending_exception) {
+Symbol* ConstantPool::exception_message(const constantPoolHandle& this_cp, int which, constantTag tag, oop pending_exception) {
   // Dig out the detailed message to reuse if possible
   Symbol* message = java_lang_Throwable::detail_message(pending_exception);
   if (message != NULL) {
@@ -554,7 +554,7 @@
   return message;
 }
 
-void ConstantPool::throw_resolution_error(constantPoolHandle this_cp, int which, TRAPS) {
+void ConstantPool::throw_resolution_error(const constantPoolHandle& this_cp, int which, TRAPS) {
   Symbol* message = NULL;
   Symbol* error = SystemDictionary::find_resolution_error(this_cp, which, &message);
   assert(error != NULL && message != NULL, "checking");
@@ -565,7 +565,7 @@
 
 // If resolution for Class, 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_cp, int which,
+void ConstantPool::save_and_throw_exception(const constantPoolHandle& this_cp, int which,
                                             constantTag tag, TRAPS) {
   Symbol* error = PENDING_EXCEPTION->klass()->name();
 
@@ -603,7 +603,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_cp, int index, int cache_index, TRAPS) {
+oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index, TRAPS) {
   oop result_oop = NULL;
   Handle throw_exception;
 
@@ -756,7 +756,7 @@
 }
 
 
-oop ConstantPool::resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp, int index, TRAPS) {
+oop ConstantPool::resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS) {
   assert(this_cp->tag_at(index).is_invoke_dynamic(), "Corrupted constant pool");
 
   Handle bsm;
@@ -794,7 +794,7 @@
   return info();
 }
 
-oop ConstantPool::string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS) {
+oop ConstantPool::string_at_impl(const 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_cp->resolved_references()->obj_at(obj_index);
   if (str != NULL) return str;
@@ -830,7 +830,7 @@
 
 // Compare this constant pool's entry at index1 to the constant pool
 // cp2's entry at index2.
-bool ConstantPool::compare_entry_to(int index1, constantPoolHandle cp2,
+bool ConstantPool::compare_entry_to(int index1, const constantPoolHandle& cp2,
        int index2, TRAPS) {
 
   // The error tags are equivalent to non-error tags when comparing
@@ -1056,7 +1056,7 @@
 
 // Extend the operands array with the length and size of the ext_cp operands.
 // Used in RedefineClasses for CP merge.
-void ConstantPool::extend_operands(constantPoolHandle ext_cp, TRAPS) {
+void ConstantPool::extend_operands(const constantPoolHandle& ext_cp, TRAPS) {
   int delta_len = operand_array_length(ext_cp->operands());
   if (delta_len == 0) {
     return; // nothing to do
@@ -1096,8 +1096,8 @@
 } // end shrink_operands()
 
 
-void ConstantPool::copy_operands(constantPoolHandle from_cp,
-                                 constantPoolHandle to_cp,
+void ConstantPool::copy_operands(const constantPoolHandle& from_cp,
+                                 const constantPoolHandle& to_cp,
                                  TRAPS) {
 
   int from_oplen = operand_array_length(from_cp->operands());
@@ -1160,8 +1160,8 @@
 // Copy this constant pool's entries at start_i to end_i (inclusive)
 // to the constant pool to_cp's entries starting at to_i. A total of
 // (end_i - start_i) + 1 entries are copied.
-void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i,
-       constantPoolHandle to_cp, int to_i, TRAPS) {
+void ConstantPool::copy_cp_to_impl(const constantPoolHandle& from_cp, int start_i, int end_i,
+       const constantPoolHandle& to_cp, int to_i, TRAPS) {
 
 
   int dest_i = to_i;  // leave original alone for debug purposes
@@ -1191,8 +1191,8 @@
 
 // Copy this constant pool's entry at from_i to the constant pool
 // to_cp's entry at to_i.
-void ConstantPool::copy_entry_to(constantPoolHandle from_cp, int from_i,
-                                        constantPoolHandle to_cp, int to_i,
+void ConstantPool::copy_entry_to(const constantPoolHandle& from_cp, int from_i,
+                                        const constantPoolHandle& to_cp, int to_i,
                                         TRAPS) {
 
   int tag = from_cp->tag_at(from_i).value();
@@ -1339,7 +1339,7 @@
 // constant pool's entry at pattern_i. Returns the index of a
 // matching entry or zero (0) if there is no matching entry.
 int ConstantPool::find_matching_entry(int pattern_i,
-      constantPoolHandle search_cp, TRAPS) {
+      const constantPoolHandle& search_cp, TRAPS) {
 
   // index zero (0) is not used
   for (int i = 1; i < search_cp->length(); i++) {
@@ -1355,7 +1355,7 @@
 
 // Compare this constant pool's bootstrap specifier at idx1 to the constant pool
 // cp2's bootstrap specifier at idx2.
-bool ConstantPool::compare_operand_to(int idx1, constantPoolHandle cp2, int idx2, TRAPS) {
+bool ConstantPool::compare_operand_to(int idx1, const constantPoolHandle& cp2, int idx2, TRAPS) {
   int k1 = operand_bootstrap_method_ref_index_at(idx1);
   int k2 = cp2->operand_bootstrap_method_ref_index_at(idx2);
   bool match = compare_entry_to(k1, cp2, k2, CHECK_false);
@@ -1382,7 +1382,7 @@
 // this constant pool's bootstrap specifier at pattern_i index.
 // Return the index of a matching bootstrap specifier or (-1) if there is no match.
 int ConstantPool::find_matching_operand(int pattern_i,
-                    constantPoolHandle search_cp, int search_len, TRAPS) {
+                    const constantPoolHandle& search_cp, int search_len, TRAPS) {
   for (int i = 0; i < search_len; i++) {
     bool found = compare_operand_to(pattern_i, search_cp, i, CHECK_(-1));
     if (found) {
@@ -1843,7 +1843,7 @@
     if (cp->tag_at(i).is_unresolved_klass()) {
       // This will force loading of the class
       Klass* klass = cp->klass_at(i, CHECK);
-      if (klass->oop_is_instance()) {
+      if (klass->is_instance_klass()) {
         // Force initialization of class
         InstanceKlass::cast(klass)->initialize(CHECK);
       }
--- a/hotspot/src/share/vm/oops/constantPool.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/constantPool.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -604,15 +604,15 @@
     return offset;
   }
   // Compare a bootsrap specifier in the operands arrays
-  bool compare_operand_to(int bootstrap_specifier_index1, constantPoolHandle cp2,
+  bool compare_operand_to(int bootstrap_specifier_index1, const constantPoolHandle& cp2,
                           int bootstrap_specifier_index2, TRAPS);
   // Find a bootsrap specifier in the operands array
-  int find_matching_operand(int bootstrap_specifier_index, constantPoolHandle search_cp,
+  int find_matching_operand(int bootstrap_specifier_index, const constantPoolHandle& search_cp,
                             int operands_cur_len, TRAPS);
   // Resize the operands array with delta_len and delta_size
   void resize_operands(int delta_len, int delta_size, TRAPS);
   // Extend the operands array with the length and size of the ext_cp operands
-  void extend_operands(constantPoolHandle ext_cp, TRAPS);
+  void extend_operands(const constantPoolHandle& ext_cp, TRAPS);
   // Shrink the operands array to a smaller array with new_len length
   void shrink_operands(int new_len, TRAPS);
 
@@ -735,13 +735,13 @@
   friend class SystemDictionary;
 
   // Used by compiler to prevent classloading.
-  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);
+  static Method*          method_at_if_loaded      (const constantPoolHandle& this_cp, int which);
+  static bool       has_appendix_at_if_loaded      (const constantPoolHandle& this_cp, int which);
+  static oop            appendix_at_if_loaded      (const constantPoolHandle& this_cp, int which);
+  static bool    has_method_type_at_if_loaded      (const constantPoolHandle& this_cp, int which);
+  static oop         method_type_at_if_loaded      (const constantPoolHandle& this_cp, int which);
+  static Klass*            klass_at_if_loaded      (const constantPoolHandle& this_cp, int which);
+  static Klass*        klass_ref_at_if_loaded      (const 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
@@ -797,38 +797,38 @@
   }
 
   // Performs the LinkResolver checks
-  static void verify_constant_pool_resolve(constantPoolHandle this_cp, KlassHandle klass, TRAPS);
+  static void verify_constant_pool_resolve(const 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_cp, int which,
+  static Klass* klass_at_impl(const constantPoolHandle& this_cp, int which,
                               bool save_resolution_error, TRAPS);
-  static oop string_at_impl(constantPoolHandle this_cp, int which, int obj_index, TRAPS);
+  static oop string_at_impl(const constantPoolHandle& this_cp, int which, int obj_index, TRAPS);
 
-  static void trace_class_resolution(constantPoolHandle this_cp, KlassHandle k);
+  static void trace_class_resolution(const constantPoolHandle& this_cp, KlassHandle k);
 
   // Resolve string constants (to prevent allocation during compilation)
-  static void resolve_string_constants_impl(constantPoolHandle this_cp, TRAPS);
+  static void resolve_string_constants_impl(const constantPoolHandle& this_cp, TRAPS);
 
-  static oop resolve_constant_at_impl(constantPoolHandle this_cp, int index, int cache_index, TRAPS);
-  static oop resolve_bootstrap_specifier_at_impl(constantPoolHandle this_cp, int index, TRAPS);
+  static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index, TRAPS);
+  static oop resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS);
 
   // Exception handling
-  static void throw_resolution_error(constantPoolHandle this_cp, int which, TRAPS);
-  static Symbol* exception_message(constantPoolHandle this_cp, int which, constantTag tag, oop pending_exception);
-  static void save_and_throw_exception(constantPoolHandle this_cp, int which, constantTag tag, TRAPS);
+  static void throw_resolution_error(const constantPoolHandle& this_cp, int which, TRAPS);
+  static Symbol* exception_message(const constantPoolHandle& this_cp, int which, constantTag tag, oop pending_exception);
+  static void save_and_throw_exception(const constantPoolHandle& this_cp, int which, constantTag tag, TRAPS);
 
  public:
   // Merging ConstantPool* support:
-  bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS);
-  void copy_cp_to(int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS) {
+  bool compare_entry_to(int index1, const constantPoolHandle& cp2, int index2, TRAPS);
+  void copy_cp_to(int start_i, int end_i, const constantPoolHandle& to_cp, int to_i, TRAPS) {
     constantPoolHandle h_this(THREAD, this);
     copy_cp_to_impl(h_this, start_i, end_i, to_cp, to_i, THREAD);
   }
-  static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS);
-  static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS);
-  static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS);
-  int  find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS);
+  static void copy_cp_to_impl(const constantPoolHandle& from_cp, int start_i, int end_i, const constantPoolHandle& to_cp, int to_i, TRAPS);
+  static void copy_entry_to(const constantPoolHandle& from_cp, int from_i, const constantPoolHandle& to_cp, int to_i, TRAPS);
+  static void copy_operands(const constantPoolHandle& from_cp, const constantPoolHandle& to_cp, TRAPS);
+  int  find_matching_entry(int pattern_i, const constantPoolHandle& search_cp, TRAPS);
   int  version() const                    { return _saved._version; }
   void set_version(int version)           { _saved._version = version; }
   void increment_and_save_version(int version) {
--- a/hotspot/src/share/vm/oops/cpCache.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/cpCache.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -246,7 +246,7 @@
   set_direct_or_vtable_call(invoke_code, method, index);
 }
 
-void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) {
+void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, const methodHandle& method, int index) {
   assert(method->method_holder()->verify_itable_index(index), "");
   assert(invoke_code == Bytecodes::_invokeinterface, "");
   InstanceKlass* interf = method->method_holder();
@@ -261,15 +261,15 @@
 }
 
 
-void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, const CallInfo &call_info) {
+void ConstantPoolCacheEntry::set_method_handle(const constantPoolHandle& cpool, const CallInfo &call_info) {
   set_method_handle_common(cpool, Bytecodes::_invokehandle, call_info);
 }
 
-void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, const CallInfo &call_info) {
+void ConstantPoolCacheEntry::set_dynamic_call(const constantPoolHandle& cpool, const CallInfo &call_info) {
   set_method_handle_common(cpool, Bytecodes::_invokedynamic, call_info);
 }
 
-void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
+void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle& cpool,
                                                       Bytecodes::Code invoke_code,
                                                       const CallInfo &call_info) {
   // NOTE: This CPCE can be the subject of data races.
@@ -361,7 +361,7 @@
   }
 }
 
-Method* ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) {
+Method* ConstantPoolCacheEntry::method_if_resolved(const constantPoolHandle& cpool) {
   // Decode the action of set_method and set_interface_call
   Bytecodes::Code invoke_code = bytecode_1();
   if (invoke_code != (Bytecodes::Code)0) {
@@ -394,7 +394,7 @@
         int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index());
         if (cpool->tag_at(holder_index).is_klass()) {
           Klass* klass = cpool->resolved_klass_at(holder_index);
-          if (!klass->oop_is_instance())
+          if (!klass->is_instance_klass())
             klass = SystemDictionary::Object_klass();
           return InstanceKlass::cast(klass)->method_at_vtable(f2_as_index());
         }
@@ -406,7 +406,7 @@
 }
 
 
-oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) {
+oop ConstantPoolCacheEntry::appendix_if_resolved(const constantPoolHandle& cpool) {
   if (!has_appendix())
     return NULL;
   const int ref_index = f2_as_index() + _indy_resolved_references_appendix_offset;
@@ -415,7 +415,7 @@
 }
 
 
-oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) {
+oop ConstantPoolCacheEntry::method_type_if_resolved(const constantPoolHandle& cpool) {
   if (!has_method_type())
     return NULL;
   const int ref_index = f2_as_index() + _indy_resolved_references_method_type_offset;
--- a/hotspot/src/share/vm/oops/cpCache.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/cpCache.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -246,17 +246,17 @@
 
   void set_itable_call(
     Bytecodes::Code invoke_code,                 // the bytecode used; must be invokeinterface
-    methodHandle method,                         // the resolved interface method
+    const methodHandle& method,                  // the resolved interface method
     int itable_index                             // index into itable for the method
   );
 
   void set_method_handle(
-    constantPoolHandle cpool,                    // holding constant pool (required for locking)
+    const constantPoolHandle& cpool,             // holding constant pool (required for locking)
     const CallInfo &call_info                    // Call link information
   );
 
   void set_dynamic_call(
-    constantPoolHandle cpool,                    // holding constant pool (required for locking)
+    const constantPoolHandle& cpool,             // holding constant pool (required for locking)
     const CallInfo &call_info                    // Call link information
   );
 
@@ -276,7 +276,7 @@
   // resolution logic needs to make slightly different assessments about the
   // number and types of arguments.
   void set_method_handle_common(
-    constantPoolHandle cpool,                    // holding constant pool (required for locking)
+    const constantPoolHandle& cpool,                    // holding constant pool (required for locking)
     Bytecodes::Code invoke_code,                 // _invokehandle or _invokedynamic
     const CallInfo &call_info                    // Call link information
   );
@@ -291,9 +291,9 @@
     _indy_resolved_references_entries
   };
 
-  Method*      method_if_resolved(constantPoolHandle cpool);
-  oop        appendix_if_resolved(constantPoolHandle cpool);
-  oop     method_type_if_resolved(constantPoolHandle cpool);
+  Method*      method_if_resolved(const constantPoolHandle& cpool);
+  oop        appendix_if_resolved(const constantPoolHandle& cpool);
+  oop     method_type_if_resolved(const constantPoolHandle& cpool);
 
   void set_parameter_size(int value);
 
--- a/hotspot/src/share/vm/oops/fieldInfo.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/fieldInfo.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -176,7 +176,7 @@
     return (_shorts[low_packed_offset] & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET;
   }
 
-  Symbol* name(constantPoolHandle cp) const {
+  Symbol* name(const constantPoolHandle& cp) const {
     int index = name_index();
     if (is_internal()) {
       return lookup_symbol(index);
@@ -184,7 +184,7 @@
     return cp->symbol_at(index);
   }
 
-  Symbol* signature(constantPoolHandle cp) const {
+  Symbol* signature(const constantPoolHandle& cp) const {
     int index = signature_index();
     if (is_internal()) {
       return lookup_symbol(index);
--- a/hotspot/src/share/vm/oops/fieldStreams.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/fieldStreams.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@
     return num_fields;
   }
 
-  FieldStreamBase(Array<u2>* fields, constantPoolHandle constants, int start, int limit) {
+  FieldStreamBase(Array<u2>* fields, const constantPoolHandle& constants, int start, int limit) {
     _fields = fields;
     _constants = constants;
     _index = start;
@@ -91,7 +91,7 @@
     }
   }
 
-  FieldStreamBase(Array<u2>* fields, constantPoolHandle constants) {
+  FieldStreamBase(Array<u2>* fields, const constantPoolHandle& constants) {
     _fields = fields;
     _constants = constants;
     _index = 0;
@@ -251,7 +251,7 @@
 
 class AllFieldStream : public FieldStreamBase {
  public:
-  AllFieldStream(Array<u2>* fields, constantPoolHandle constants): FieldStreamBase(fields, constants) {}
+  AllFieldStream(Array<u2>* fields, const constantPoolHandle& constants): FieldStreamBase(fields, constants) {}
   AllFieldStream(InstanceKlass* k):      FieldStreamBase(k->fields(), k->constants()) {}
   AllFieldStream(instanceKlassHandle k): FieldStreamBase(k->fields(), k->constants()) {}
 };
--- a/hotspot/src/share/vm/oops/generateOopMap.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -222,7 +222,7 @@
   }
 }
 
-void RetTable::compute_ret_table(methodHandle method) {
+void RetTable::compute_ret_table(const methodHandle& method) {
   BytecodeStream i(method);
   Bytecodes::Code bytecode;
 
@@ -2039,7 +2039,7 @@
 //
 //  ============ Main Entry Point ===========
 //
-GenerateOopMap::GenerateOopMap(methodHandle method) {
+GenerateOopMap::GenerateOopMap(const methodHandle& method) {
   // We have to initialize all variables here, that can be queried directly
   _method = method;
   _max_locals=0;
--- a/hotspot/src/share/vm/oops/generateOopMap.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/generateOopMap.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,7 +78,7 @@
   void add_jsr(int return_bci, int target_bci);   // Adds entry to list
  public:
   RetTable()                                                  { _first = NULL; }
-  void compute_ret_table(methodHandle method);
+  void compute_ret_table(const methodHandle& method);
   void update_ret_table(int bci, int delta);
   RetTableEntry* find_jsrs_for_target(int targBci);
 };
@@ -462,7 +462,7 @@
 
   friend class RelocCallback;
  public:
-  GenerateOopMap(methodHandle method);
+  GenerateOopMap(const methodHandle& method);
 
   // Compute the map.
   void compute_map(TRAPS);
@@ -537,7 +537,7 @@
 #endif
 
  public:
-  ResolveOopMapConflicts(methodHandle method) : GenerateOopMap(method) { _must_clear_locals = false; };
+  ResolveOopMapConflicts(const methodHandle& method) : GenerateOopMap(method) { _must_clear_locals = false; };
 
   methodHandle do_potential_rewrite(TRAPS);
   bool must_clear_locals() const { return _must_clear_locals; }
@@ -562,7 +562,7 @@
                                            int stack_top)                 {}
   virtual void fill_init_vars             (GrowableArray<intptr_t> *init_vars) {}
  public:
-  GeneratePairingInfo(methodHandle method) : GenerateOopMap(method)       {};
+  GeneratePairingInfo(const methodHandle& method) : GenerateOopMap(method)       {};
 
   // Call compute_map(CHECK) to generate info.
 };
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -742,7 +742,7 @@
   // A class could already be verified, since it has been reflected upon.
   this_k->link_class(CHECK);
 
-  DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_k()), -1);
+  DTRACE_CLASSINIT_PROBE(required, this_k(), -1);
 
   bool wait = false;
 
@@ -765,19 +765,19 @@
 
     // Step 3
     if (this_k->is_being_initialized() && this_k->is_reentrant_initialization(self)) {
-      DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_k()), -1,wait);
+      DTRACE_CLASSINIT_PROBE_WAIT(recursive, this_k(), -1,wait);
       return;
     }
 
     // Step 4
     if (this_k->is_initialized()) {
-      DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_k()), -1,wait);
+      DTRACE_CLASSINIT_PROBE_WAIT(concurrent, this_k(), -1,wait);
       return;
     }
 
     // Step 5
     if (this_k->is_in_error_state()) {
-      DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_k()), -1,wait);
+      DTRACE_CLASSINIT_PROBE_WAIT(erroneous, this_k(), -1,wait);
       ResourceMark rm(THREAD);
       const char* desc = "Could not initialize class ";
       const char* className = this_k->external_name();
@@ -810,7 +810,7 @@
         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_k()), -1,wait);
+      DTRACE_CLASSINIT_PROBE_WAIT(super__failed, this_k(), -1,wait);
       THROW_OOP(e());
     }
   }
@@ -826,7 +826,7 @@
   {
     assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
     JavaThread* jt = (JavaThread*)THREAD;
-    DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_k()), -1,wait);
+    DTRACE_CLASSINIT_PROBE_WAIT(clinit, 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(),
@@ -860,7 +860,7 @@
       // 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_k()), -1,wait);
+    DTRACE_CLASSINIT_PROBE_WAIT(error, this_k(), -1,wait);
     if (e->is_a(SystemDictionary::Error_klass())) {
       THROW_OOP(e());
     } else {
@@ -870,7 +870,7 @@
                 &args);
     }
   }
-  DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_k()), -1,wait);
+  DTRACE_CLASSINIT_PROBE_WAIT(end, this_k(), -1,wait);
 }
 
 
@@ -907,7 +907,7 @@
   // Filter out subclasses whose supers already implement me.
   // (Note: CHA must walk subclasses of direct implementors
   // in order to locate indirect implementors.)
-  Klass* sk = InstanceKlass::cast(k)->super();
+  Klass* sk = k->super();
   if (sk != NULL && InstanceKlass::cast(sk)->implements_interface(this))
     // We only need to check one immediate superclass, since the
     // implements_interface query looks at transitive_interfaces.
@@ -955,8 +955,7 @@
 
 GrowableArray<Klass*>* InstanceKlass::compute_secondary_supers(int num_extra_slots) {
   // The secondaries are the implemented interfaces.
-  InstanceKlass* ik = InstanceKlass::cast(this);
-  Array<Klass*>* interfaces = ik->transitive_interfaces();
+  Array<Klass*>* interfaces = transitive_interfaces();
   int num_secondaries = num_extra_slots + interfaces->length();
   if (num_secondaries == 0) {
     // Must share this for correct bootstrapping!
@@ -1141,7 +1140,7 @@
 }
 
 
-void InstanceKlass::mask_for(methodHandle method, int bci,
+void InstanceKlass::mask_for(const methodHandle& method, int bci,
   InterpreterOopMap* entry_for) {
   // Dirty read, then double-check under a lock.
   if (_oop_map_cache == NULL) {
@@ -1532,7 +1531,7 @@
     if (method != NULL) {
       return method;
     }
-    klass = InstanceKlass::cast(klass)->super();
+    klass = klass->super();
     overpass_local_mode = skip_overpass;   // Always ignore overpass methods in superclasses
   }
   return NULL;
@@ -1541,13 +1540,13 @@
 #ifdef ASSERT
 // search through class hierarchy and return true if this class or
 // one of the superclasses was redefined
-bool InstanceKlass::has_redefined_this_or_super() const {
-  const InstanceKlass* klass = this;
+bool InstanceKlass::has_redefined_this_or_super() {
+  Klass* klass = this;
   while (klass != NULL) {
-    if (klass->has_been_redefined()) {
+    if (InstanceKlass::cast(klass)->has_been_redefined()) {
       return true;
     }
-    klass = InstanceKlass::cast(klass->super());
+    klass = klass->super();
   }
   return false;
 }
@@ -1645,7 +1644,7 @@
 // locking has to be done very carefully to avoid deadlocks
 // and/or other cache consistency problems.
 //
-jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, methodHandle method_h) {
+jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, const methodHandle& method_h) {
   size_t idnum = (size_t)method_h->method_idnum();
   jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire();
   size_t length = 0;
@@ -1907,18 +1906,33 @@
 // Decrement count of the nmethod in the dependency list and remove
 // the bucket completely when the count goes to 0.  This method must
 // find a corresponding bucket otherwise there's a bug in the
-// recording of dependencies. Returns true if the bucket is ready for reclamation.
-//
-bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
+// recording of dependencies. Returns true if the bucket was deleted,
+// or marked ready for reclaimation.
+bool nmethodBucket::remove_dependent_nmethod(nmethodBucket** deps, nmethod* nm, bool delete_immediately) {
   assert_locked_or_safepoint(CodeCache_lock);
 
-  for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+  nmethodBucket* first = *deps;
+  nmethodBucket* last = NULL;
+
+  for (nmethodBucket* b = first; b != NULL; b = b->next()) {
     if (nm == b->get_nmethod()) {
       int val = b->decrement();
       guarantee(val >= 0, "Underflow: %d", val);
-      return (val == 0);
+      if (val == 0) {
+        if (delete_immediately) {
+          if (last == NULL) {
+            *deps = b->next();
+          } else {
+            last->set_next(b->next());
+          }
+          delete b;
+        }
+      }
+      return true;
     }
+    last = b;
   }
+
 #ifdef ASSERT
   tty->print_raw_cr("### can't find dependent nmethod");
   nm->print();
@@ -1927,6 +1941,12 @@
   return false;
 }
 
+// Convenience overload, for callers that don't want to delete the nmethodBucket entry.
+bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
+  nmethodBucket** deps_addr = &deps;
+  return remove_dependent_nmethod(deps_addr, nm, false /* Don't delete */);
+}
+
 //
 // Reclaim all unused buckets. Returns new head of the list.
 //
@@ -2013,10 +2033,10 @@
   _dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm);
 }
 
-void InstanceKlass::remove_dependent_nmethod(nmethod* nm) {
+void InstanceKlass::remove_dependent_nmethod(nmethod* nm, bool delete_immediately) {
   assert_locked_or_safepoint(CodeCache_lock);
 
-  if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) {
+  if (nmethodBucket::remove_dependent_nmethod(&_dependencies, nm, delete_immediately)) {
     set_has_unloaded_dependent(true);
   }
 }
@@ -2031,6 +2051,13 @@
 }
 #endif //PRODUCT
 
+void InstanceKlass::clean_weak_instanceklass_links(BoolObjectClosure* is_alive) {
+  clean_implementors_list(is_alive);
+  clean_method_data(is_alive);
+
+  clean_dependent_nmethods();
+}
+
 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
   assert(class_loader_data()->is_alive(is_alive), "this klass should be live");
   if (is_interface()) {
@@ -2297,32 +2324,18 @@
 
 // different verisons of is_same_class_package
 bool InstanceKlass::is_same_class_package(Klass* class2) {
-  Klass* class1 = this;
-  oop classloader1 = InstanceKlass::cast(class1)->class_loader();
-  Symbol* classname1 = class1->name();
-
-  if (class2->oop_is_objArray()) {
+  if (class2->is_objArray_klass()) {
     class2 = ObjArrayKlass::cast(class2)->bottom_klass();
   }
-  oop classloader2;
-  if (class2->oop_is_instance()) {
-    classloader2 = InstanceKlass::cast(class2)->class_loader();
-  } else {
-    assert(class2->oop_is_typeArray(), "should be type array");
-    classloader2 = NULL;
-  }
+  oop classloader2 = class2->class_loader();
   Symbol* classname2 = class2->name();
 
-  return InstanceKlass::is_same_class_package(classloader1, classname1,
+  return InstanceKlass::is_same_class_package(class_loader(), name(),
                                               classloader2, classname2);
 }
 
 bool InstanceKlass::is_same_class_package(oop classloader2, Symbol* classname2) {
-  Klass* class1 = this;
-  oop classloader1 = InstanceKlass::cast(class1)->class_loader();
-  Symbol* classname1 = class1->name();
-
-  return InstanceKlass::is_same_class_package(classloader1, classname1,
+  return InstanceKlass::is_same_class_package(class_loader(), name(),
                                               classloader2, classname2);
 }
 
@@ -2385,7 +2398,7 @@
 // Assumes name-signature match
 // "this" is InstanceKlass of super_method which must exist
 // note that the InstanceKlass of the method in the targetclassname has not always been created yet
-bool InstanceKlass::is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS) {
+bool InstanceKlass::is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS) {
    // Private methods can not be overridden
    if (super_method->is_private()) {
      return false;
@@ -2411,7 +2424,7 @@
 bool InstanceKlass::is_same_package_member_impl(instanceKlassHandle class1,
                                                 Klass* class2_oop, TRAPS) {
   if (class2_oop == class1())                       return true;
-  if (!class2_oop->oop_is_instance())  return false;
+  if (!class2_oop->is_instance_klass())  return false;
   instanceKlassHandle class2(THREAD, class2_oop);
 
   // must be in same package before we try anything else
@@ -2882,7 +2895,8 @@
   ((InstanceKlass*)this)->do_local_static_fields(&print_static_field);
   st->print_cr(BULLET"---- non-static fields (%d words):", nonstatic_field_size());
   FieldPrinter print_nonstatic_field(st);
-  ((InstanceKlass*)this)->do_nonstatic_fields(&print_nonstatic_field);
+  InstanceKlass* ik = const_cast<InstanceKlass*>(this);
+  ik->do_nonstatic_fields(&print_nonstatic_field);
 
   st->print(BULLET"non-static oop maps: ");
   OopMapBlock* map     = start_of_nonstatic_oop_maps();
@@ -2921,12 +2935,10 @@
 
   if (this == SystemDictionary::String_klass()) {
     typeArrayOop value  = java_lang_String::value(obj);
-    juint        offset = java_lang_String::offset(obj);
     juint        length = java_lang_String::length(obj);
     if (value != NULL &&
         value->is_typeArray() &&
-        offset          <= (juint) value->length() &&
-        offset + length <= (juint) value->length()) {
+        length <= (juint) value->length()) {
       st->print(BULLET"string: ");
       java_lang_String::print(obj, st);
       st->cr();
@@ -2953,7 +2965,7 @@
     st->print_cr(BULLET"fake entry for oop_size: %d", java_lang_Class::oop_size(obj));
     st->print_cr(BULLET"fake entry for static_oop_field_count: %d", java_lang_Class::static_oop_field_count(obj));
     Klass* real_klass = java_lang_Class::as_Klass(obj);
-    if (real_klass != NULL && real_klass->oop_is_instance()) {
+    if (real_klass != NULL && real_klass->is_instance_klass()) {
       InstanceKlass::cast(real_klass)->do_local_static_fields(&print_field);
     }
   } else if (this == SystemDictionary::MethodType_klass()) {
@@ -3546,3 +3558,199 @@
 unsigned char * InstanceKlass::get_cached_class_file_bytes() {
   return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
 }
+
+
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+
+class TestNmethodBucketContext {
+ public:
+  nmethod* _nmethodLast;
+  nmethod* _nmethodMiddle;
+  nmethod* _nmethodFirst;
+
+  nmethodBucket* _bucketLast;
+  nmethodBucket* _bucketMiddle;
+  nmethodBucket* _bucketFirst;
+
+  nmethodBucket* _bucketList;
+
+  TestNmethodBucketContext() {
+    CodeCache_lock->lock_without_safepoint_check();
+
+    _nmethodLast   = reinterpret_cast<nmethod*>(0x8 * 0);
+    _nmethodMiddle = reinterpret_cast<nmethod*>(0x8 * 1);
+    _nmethodFirst  = reinterpret_cast<nmethod*>(0x8 * 2);
+
+    _bucketLast   = new nmethodBucket(_nmethodLast,   NULL);
+    _bucketMiddle = new nmethodBucket(_nmethodMiddle, _bucketLast);
+    _bucketFirst  = new nmethodBucket(_nmethodFirst,   _bucketMiddle);
+
+    _bucketList = _bucketFirst;
+  }
+
+  ~TestNmethodBucketContext() {
+    delete _bucketLast;
+    delete _bucketMiddle;
+    delete _bucketFirst;
+
+    CodeCache_lock->unlock();
+  }
+};
+
+class TestNmethodBucket {
+ public:
+  static void testRemoveDependentNmethodFirstDeleteImmediately() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodFirst, true /* delete */);
+
+    assert(c._bucketList == c._bucketMiddle, "check");
+    assert(c._bucketList->next() == c._bucketLast, "check");
+    assert(c._bucketList->next()->next() == NULL, "check");
+
+    // Cleanup before context is deleted.
+    c._bucketFirst = NULL;
+  }
+
+  static void testRemoveDependentNmethodMiddleDeleteImmediately() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodMiddle, true /* delete */);
+
+    assert(c._bucketList == c._bucketFirst, "check");
+    assert(c._bucketList->next() == c._bucketLast, "check");
+    assert(c._bucketList->next()->next() == NULL, "check");
+
+    // Cleanup before context is deleted.
+    c._bucketMiddle = NULL;
+  }
+
+  static void testRemoveDependentNmethodLastDeleteImmediately() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodLast, true /* delete */);
+
+    assert(c._bucketList == c._bucketFirst, "check");
+    assert(c._bucketList->next() == c._bucketMiddle, "check");
+    assert(c._bucketList->next()->next() == NULL, "check");
+
+    // Cleanup before context is deleted.
+    c._bucketLast = NULL;
+  }
+
+  static void testRemoveDependentNmethodFirstDeleteDeferred() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodFirst, false /* delete */);
+
+    assert(c._bucketList                         == c._bucketFirst,  "check");
+    assert(c._bucketList->next()                 == c._bucketMiddle, "check");
+    assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
+    assert(c._bucketList->next()->next()->next() == NULL,            "check");
+
+    assert(c._bucketFirst->count()  == 0, "check");
+    assert(c._bucketMiddle->count() == 1, "check");
+    assert(c._bucketLast->count()   == 1, "check");
+  }
+
+  static void testRemoveDependentNmethodMiddleDeleteDeferred() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodMiddle, false /* delete */);
+
+    assert(c._bucketList                         == c._bucketFirst,  "check");
+    assert(c._bucketList->next()                 == c._bucketMiddle, "check");
+    assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
+    assert(c._bucketList->next()->next()->next() == NULL,            "check");
+
+    assert(c._bucketFirst->count()  == 1, "check");
+    assert(c._bucketMiddle->count() == 0, "check");
+    assert(c._bucketLast->count()   == 1, "check");
+  }
+
+  static void testRemoveDependentNmethodLastDeleteDeferred() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodLast, false /* delete */);
+
+    assert(c._bucketList                         == c._bucketFirst,  "check");
+    assert(c._bucketList->next()                 == c._bucketMiddle, "check");
+    assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
+    assert(c._bucketList->next()->next()->next() == NULL,            "check");
+
+    assert(c._bucketFirst->count()  == 1, "check");
+    assert(c._bucketMiddle->count() == 1, "check");
+    assert(c._bucketLast->count()   == 0, "check");
+  }
+
+  static void testRemoveDependentNmethodConvenienceFirst() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodFirst);
+
+    assert(c._bucketList                         == c._bucketFirst,  "check");
+    assert(c._bucketList->next()                 == c._bucketMiddle, "check");
+    assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
+    assert(c._bucketList->next()->next()->next() == NULL,            "check");
+
+    assert(c._bucketFirst->count()  == 0, "check");
+    assert(c._bucketMiddle->count() == 1, "check");
+    assert(c._bucketLast->count()   == 1, "check");
+  }
+
+  static void testRemoveDependentNmethodConvenienceMiddle() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodMiddle);
+
+    assert(c._bucketList                         == c._bucketFirst,  "check");
+    assert(c._bucketList->next()                 == c._bucketMiddle, "check");
+    assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
+    assert(c._bucketList->next()->next()->next() == NULL,            "check");
+
+    assert(c._bucketFirst->count()  == 1, "check");
+    assert(c._bucketMiddle->count() == 0, "check");
+    assert(c._bucketLast->count()   == 1, "check");
+  }
+
+  static void testRemoveDependentNmethodConvenienceLast() {
+    TestNmethodBucketContext c;
+
+    nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodLast);
+
+    assert(c._bucketList                         == c._bucketFirst,  "check");
+    assert(c._bucketList->next()                 == c._bucketMiddle, "check");
+    assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
+    assert(c._bucketList->next()->next()->next() == NULL,            "check");
+
+    assert(c._bucketFirst->count()  == 1, "check");
+    assert(c._bucketMiddle->count() == 1, "check");
+    assert(c._bucketLast->count()   == 0, "check");
+  }
+
+  static void testRemoveDependentNmethod() {
+    testRemoveDependentNmethodFirstDeleteImmediately();
+    testRemoveDependentNmethodMiddleDeleteImmediately();
+    testRemoveDependentNmethodLastDeleteImmediately();
+
+    testRemoveDependentNmethodFirstDeleteDeferred();
+    testRemoveDependentNmethodMiddleDeleteDeferred();
+    testRemoveDependentNmethodLastDeleteDeferred();
+
+    testRemoveDependentNmethodConvenienceFirst();
+    testRemoveDependentNmethodConvenienceMiddle();
+    testRemoveDependentNmethodConvenienceLast();
+  }
+
+  static void test() {
+    testRemoveDependentNmethod();
+  }
+};
+
+void TestNmethodBucket_test() {
+  TestNmethodBucket::test();
+}
+
+#endif
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -414,7 +414,7 @@
   };
 
   // method override check
-  bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
+  bool is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
 
   // package
   bool is_same_class_package(Klass* class2);
@@ -780,7 +780,7 @@
 
   // jmethodID support
   static jmethodID get_jmethod_id(instanceKlassHandle ik_h,
-                     methodHandle method_h);
+                     const methodHandle& method_h);
   static jmethodID get_jmethod_id_fetch_or_update(instanceKlassHandle ik_h,
                      size_t idnum, jmethodID new_id, jmethodID* new_jmeths,
                      jmethodID* to_dealloc_id_p,
@@ -827,7 +827,7 @@
   // OopMapCache support
   OopMapCache* oop_map_cache()               { return _oop_map_cache; }
   void set_oop_map_cache(OopMapCache *cache) { _oop_map_cache = cache; }
-  void mask_for(methodHandle method, int bci, InterpreterOopMap* entry);
+  void mask_for(const methodHandle& method, int bci, InterpreterOopMap* entry);
 
   // JNI identifier support (for static fields - for jni performance)
   JNIid* jni_ids()                               { return _jni_ids; }
@@ -837,7 +837,7 @@
   // maintenance of deoptimization dependencies
   int mark_dependent_nmethods(DepChange& changes);
   void add_dependent_nmethod(nmethod* nm);
-  void remove_dependent_nmethod(nmethod* nm);
+  void remove_dependent_nmethod(nmethod* nm, bool delete_immediately);
 
   // On-stack replacement support
   nmethod* osr_nmethods_head() const         { return _osr_nmethods_head; };
@@ -862,7 +862,7 @@
 
 #ifdef ASSERT
   // check whether this class or one of its superclasses was redefined
-  bool has_redefined_this_or_super() const;
+  bool has_redefined_this_or_super();
 #endif
 
   // Access to the implementor of an interface.
@@ -908,7 +908,9 @@
   bool compute_is_subtype_of(Klass* k);
   bool can_be_primary_super_slow() const;
   int oop_size(oop obj)  const             { return size_helper(); }
-  bool oop_is_instance_slow() const        { return true; }
+  // slow because it's a virtual call and used for verifying the layout_helper.
+  // Using the layout_helper bits, we can call is_instance_klass without a virtual call.
+  DEBUG_ONLY(bool is_instance_klass_slow() const      { return true; })
 
   // Iterators
   void do_local_static_fields(FieldClosure* cl);
@@ -922,7 +924,8 @@
 
   // Casting from Klass*
   static InstanceKlass* cast(Klass* k) {
-    assert(k == NULL || k->oop_is_instance(), "cast to InstanceKlass");
+    assert(k != NULL, "k should not be null");
+    assert(k->is_instance_klass(), "cast to InstanceKlass");
     return static_cast<InstanceKlass*>(k);
   }
 
@@ -1021,6 +1024,7 @@
   void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed);
 #endif // INCLUDE_JVMTI
 
+  void clean_weak_instanceklass_links(BoolObjectClosure* is_alive);
   void clean_implementors_list(BoolObjectClosure* is_alive);
   void clean_method_data(BoolObjectClosure* is_alive);
   void clean_dependent_nmethods();
@@ -1349,6 +1353,7 @@
 
   static int mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes);
   static nmethodBucket* add_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
+  static bool remove_dependent_nmethod(nmethodBucket** deps, nmethod* nm, bool delete_immediately);
   static bool remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
   static nmethodBucket* clean_dependent_nmethods(nmethodBucket* deps);
 #ifndef PRODUCT
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -40,7 +40,7 @@
 int InstanceMirrorKlass::_offset_of_static_fields = 0;
 
 int InstanceMirrorKlass::instance_size(KlassHandle k) {
-  if (k() != NULL && k->oop_is_instance()) {
+  if (k() != NULL && k->is_instance_klass()) {
     return align_object_size(size_helper() + InstanceKlass::cast(k())->static_field_size());
   }
   return size_helper();
@@ -65,7 +65,7 @@
 
 int InstanceMirrorKlass::compute_static_oop_field_count(oop obj) {
   Klass* k = java_lang_Class::as_Klass(obj);
-  if (k != NULL && k->oop_is_instance()) {
+  if (k != NULL && k->is_instance_klass()) {
     return InstanceKlass::cast(k)->static_oop_field_count();
   }
   return 0;
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.inline.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.inline.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -60,7 +60,7 @@
     Klass* klass = java_lang_Class::as_Klass(obj);
     // We'll get NULL for primitive mirrors.
     if (klass != NULL) {
-      if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
+      if (klass->is_instance_klass() && InstanceKlass::cast(klass)->is_anonymous()) {
         // An anonymous class doesn't have its own class loader, so when handling
         // the java mirror for an anonymous class we need to make sure its class
         // loader data is claimed, this is done by calling do_cld explicitly.
--- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -82,8 +82,9 @@
   // Verify next field
   oop next = java_lang_ref_Reference::next(obj);
   if (next != NULL) {
-    guarantee(next->is_oop(), "next field verify failed");
-    guarantee(next->is_instanceRef(), "next field verify failed");
+    guarantee(next->is_oop(), "next field should be an oop");
+    guarantee(next->is_instance(), "next field should be an instance");
+    guarantee(InstanceKlass::cast(next->klass())->is_reference_instance_klass(), "next field verify failed");
   }
 }
 
--- a/hotspot/src/share/vm/oops/klass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/klass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -348,7 +348,7 @@
 
 
 InstanceKlass* Klass::superklass() const {
-  assert(super() == NULL || super()->oop_is_instance(), "must be instance klass");
+  assert(super() == NULL || super()->is_instance_klass(), "must be instance klass");
   return _super == NULL ? NULL : InstanceKlass::cast(_super);
 }
 
@@ -440,10 +440,9 @@
     }
 
     // Clean the implementors list and method data.
-    if (clean_alive_klasses && current->oop_is_instance()) {
+    if (clean_alive_klasses && current->is_instance_klass()) {
       InstanceKlass* ik = InstanceKlass::cast(current);
-      ik->clean_implementors_list(is_alive);
-      ik->clean_method_data(is_alive);
+      ik->clean_weak_instanceklass_links(is_alive);
     }
   }
 }
@@ -558,9 +557,11 @@
 
 oop Klass::class_loader() const { return class_loader_data()->class_loader(); }
 
+// In product mode, this function doesn't have virtual function calls so
+// there might be some performance advantage to handling InstanceKlass here.
 const char* Klass::external_name() const {
-  if (oop_is_instance()) {
-    InstanceKlass* ik = (InstanceKlass*) this;
+  if (is_instance_klass()) {
+    const InstanceKlass* ik = static_cast<const InstanceKlass*>(this);
     if (ik->is_anonymous()) {
       intptr_t hash = 0;
       if (ik->java_mirror() != NULL) {
@@ -688,19 +689,13 @@
 #ifndef PRODUCT
 
 bool Klass::verify_vtable_index(int i) {
-  if (oop_is_instance()) {
-    int limit = ((InstanceKlass*)this)->vtable_length()/vtableEntry::size();
-    assert(i >= 0 && i < limit, "index %d out of bounds %d", i, limit);
-  } else {
-    assert(oop_is_array(), "Must be");
-    int limit = ((ArrayKlass*)this)->vtable_length()/vtableEntry::size();
-    assert(i >= 0 && i < limit, "index %d out of bounds %d", i, limit);
-  }
+  int limit = vtable_length()/vtableEntry::size();
+  assert(i >= 0 && i < limit, "index %d out of bounds %d", i, limit);
   return true;
 }
 
 bool Klass::verify_itable_index(int i) {
-  assert(oop_is_instance(), "");
+  assert(is_instance_klass(), "");
   int method_count = klassItable::method_count_for_interface(this);
   assert(i >= 0 && i < method_count, "index out of bounds");
   return true;
@@ -716,11 +711,11 @@
  public:
   static void test_oop_is_instanceClassLoader() {
     Klass* klass = SystemDictionary::ClassLoader_klass();
-    guarantee(klass->oop_is_instance(), "assert");
+    guarantee(klass->is_instance_klass(), "assert");
     guarantee(InstanceKlass::cast(klass)->is_class_loader_instance_klass(), "test failed");
 
     klass = SystemDictionary::String_klass();
-    guarantee(!klass->oop_is_instance() ||
+    guarantee(!klass->is_instance_klass() ||
               !InstanceKlass::cast(klass)->is_class_loader_instance_klass(),
               "test failed");
   }
@@ -730,4 +725,4 @@
   TestKlass::test_oop_is_instanceClassLoader();
 }
 
-#endif
+#endif  // PRODUCT
--- a/hotspot/src/share/vm/oops/klass.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/klass.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -373,8 +373,8 @@
 #endif
 
   // vtables
-  virtual klassVtable* vtable() const        { return NULL; }
-  virtual int vtable_length() const          { return 0; }
+  virtual klassVtable* vtable() const = 0;
+  virtual int vtable_length() const = 0;
 
   // subclass check
   bool is_subclass_of(const Klass* k) const;
@@ -474,11 +474,13 @@
   virtual const char* signature_name() const;
 
   // type testing operations
+#ifdef ASSERT
  protected:
-  virtual bool oop_is_instance_slow()       const { return false; }
-  virtual bool oop_is_array_slow()          const { return false; }
-  virtual bool oop_is_objArray_slow()       const { return false; }
-  virtual bool oop_is_typeArray_slow()      const { return false; }
+  virtual bool is_instance_klass_slow()     const { return false; }
+  virtual bool is_array_klass_slow()        const { return false; }
+  virtual bool is_objArray_klass_slow()     const { return false; }
+  virtual bool is_typeArray_klass_slow()    const { return false; }
+#endif // ASSERT
  public:
 
   // Fast non-virtual versions
@@ -492,18 +494,18 @@
   }
  public:
   #endif
-  inline  bool oop_is_instance()            const { return assert_same_query(
-                                                    layout_helper_is_instance(layout_helper()),
-                                                    oop_is_instance_slow()); }
-  inline  bool oop_is_array()               const { return assert_same_query(
+  inline  bool is_instance_klass()            const { return assert_same_query(
+                                                      layout_helper_is_instance(layout_helper()),
+                                                      is_instance_klass_slow()); }
+  inline  bool is_array_klass()               const { return assert_same_query(
                                                     layout_helper_is_array(layout_helper()),
-                                                    oop_is_array_slow()); }
-  inline  bool oop_is_objArray()            const { return assert_same_query(
+                                                    is_array_klass_slow()); }
+  inline  bool is_objArray_klass()            const { return assert_same_query(
                                                     layout_helper_is_objArray(layout_helper()),
-                                                    oop_is_objArray_slow()); }
-  inline  bool oop_is_typeArray()           const { return assert_same_query(
+                                                    is_objArray_klass_slow()); }
+  inline  bool is_typeArray_klass()           const { return assert_same_query(
                                                     layout_helper_is_typeArray(layout_helper()),
-                                                    oop_is_typeArray_slow()); }
+                                                    is_typeArray_klass_slow()); }
   #undef assert_same_query
 
   // Access flags
--- a/hotspot/src/share/vm/oops/klass.inline.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/klass.inline.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
 #include "oops/markOop.hpp"
 
 inline void Klass::set_prototype_header(markOop header) {
-  assert(!header->has_bias_pattern() || oop_is_instance(), "biased locking currently only supported for Java instances");
+  assert(!header->has_bias_pattern() || is_instance_klass(), "biased locking currently only supported for Java instances");
   _prototype_header = header;
 }
 
--- a/hotspot/src/share/vm/oops/klassVtable.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -39,9 +39,7 @@
 #include "utilities/copy.hpp"
 
 inline InstanceKlass* klassVtable::ik() const {
-  Klass* k = _klass();
-  assert(k->oop_is_instance(), "not an InstanceKlass");
-  return (InstanceKlass*)k;
+  return InstanceKlass::cast(_klass());
 }
 
 
@@ -66,8 +64,7 @@
   int vtable_length = 0;
 
   // start off with super's vtable length
-  InstanceKlass* sk = (InstanceKlass*)super;
-  vtable_length = super == NULL ? 0 : sk->vtable_length();
+  vtable_length = super == NULL ? 0 : super->vtable_length();
 
   // go thru each method in the methods table to see if it needs a new entry
   int len = methods->length();
@@ -131,10 +128,7 @@
     return 0;
   } else {
     // copy methods from superKlass
-    // can't inherit from array class, so must be InstanceKlass
-    assert(super->oop_is_instance(), "must be instance klass");
-    InstanceKlass* sk = (InstanceKlass*)super();
-    klassVtable* superVtable = sk->vtable();
+    klassVtable* superVtable = super->vtable();
     assert(superVtable->length() <= _length, "vtable too short");
 #ifdef ASSERT
     superVtable->verify(tty, true);
@@ -143,7 +137,7 @@
 #ifndef PRODUCT
     if (PrintVtables && Verbose) {
       ResourceMark rm;
-      tty->print_cr("copy vtable from %s to %s size %d", sk->internal_name(), klass()->internal_name(), _length);
+      tty->print_cr("copy vtable from %s to %s size %d", super->internal_name(), klass()->internal_name(), _length);
     }
 #endif
     return superVtable->length();
@@ -158,7 +152,7 @@
   KlassHandle super (THREAD, klass()->java_super());
   int nofNewEntries = 0;
 
-  if (PrintVtables && !klass()->oop_is_array()) {
+  if (PrintVtables && !klass()->is_array_klass()) {
     ResourceMark rm(THREAD);
     tty->print_cr("Initializing: %s", _klass->name()->as_C_string());
   }
@@ -176,10 +170,10 @@
   }
 
   int super_vtable_len = initialize_from_super(super);
-  if (klass()->oop_is_array()) {
+  if (klass()->is_array_klass()) {
     assert(super_vtable_len == _length, "arrays shouldn't introduce new methods");
   } else {
-    assert(_klass->oop_is_instance(), "must be InstanceKlass");
+    assert(_klass->is_instance_klass(), "must be InstanceKlass");
 
     Array<Method*>* methods = ik()->methods();
     int len = methods->length();
@@ -303,7 +297,7 @@
       break;
     }
     // if no override found yet, continue to search up
-    superk = InstanceKlass::cast(superk->super());
+    superk = superk->super() == NULL ? NULL : InstanceKlass::cast(superk->super());
   }
 
   return superk;
@@ -318,7 +312,7 @@
                                           bool checkconstraints, TRAPS) {
   ResourceMark rm;
   bool allocate_new = true;
-  assert(klass->oop_is_instance(), "must be InstanceKlass");
+  assert(klass->is_instance_klass(), "must be InstanceKlass");
 
   Array<int>* def_vtable_indices = NULL;
   bool is_default = false;
@@ -761,15 +755,14 @@
      return false;
    }
 
-  InstanceKlass* cursuper;
-  // Iterate on all superclasses, which should have instanceKlasses
+  // Iterate on all superclasses, which should be InstanceKlasses.
   // Note that we explicitly look for overpasses at each level.
   // Overpasses may or may not exist for supers for pass 1,
   // they should have been created for pass 2 and later.
 
-  for (cursuper = InstanceKlass::cast(super); cursuper != NULL;  cursuper = (InstanceKlass*)cursuper->super())
+  for (Klass* cursuper = super; cursuper != NULL; cursuper = cursuper->super())
   {
-     if (cursuper->find_local_method(name, signature,
+     if (InstanceKlass::cast(cursuper)->find_local_method(name, signature,
            Klass::find_overpass, Klass::skip_static, Klass::skip_private) != NULL) {
        return false;
      }
@@ -1117,7 +1110,7 @@
 }
 
 int klassItable::method_count_for_interface(Klass* interf) {
-  assert(interf->oop_is_instance(), "must be");
+  assert(interf->is_instance_klass(), "must be");
   assert(interf->is_interface(), "must be");
   Array<Method*>* methods = InstanceKlass::cast(interf)->methods();
   int nof_methods = methods->length();
@@ -1534,11 +1527,11 @@
     klassVtable* vt = kl->vtable();
     if (vt == NULL) return;
     no_klasses++;
-    if (kl->oop_is_instance()) {
+    if (kl->is_instance_klass()) {
       no_instance_klasses++;
       kl->array_klasses_do(do_class);
     }
-    if (kl->oop_is_array()) {
+    if (kl->is_array_klass()) {
       no_array_klasses++;
       sum_of_array_vtable_len += vt->length();
     }
--- a/hotspot/src/share/vm/oops/method.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -299,10 +299,7 @@
 
 
 Symbol* Method::klass_name() const {
-  Klass* k = method_holder();
-  assert(k->is_klass(), "must be klass");
-  InstanceKlass* ik = (InstanceKlass*) k;
-  return ik->name();
+  return method_holder()->name();
 }
 
 
@@ -366,7 +363,7 @@
 
 // Build a MethodData* object to hold information about this method
 // collected in the interpreter.
-void Method::build_interpreter_method_data(methodHandle method, TRAPS) {
+void Method::build_interpreter_method_data(const methodHandle& method, TRAPS) {
   // Do not profile the method if metaspace has hit an OOM previously
   // allocating profiling data. Callers clear pending exception so don't
   // add one here.
@@ -897,7 +894,7 @@
 
 // Called when the method_holder is getting linked. Setup entrypoints so the method
 // is ready to be called from interpreter, compiler, and vtables.
-void Method::link_method(methodHandle h_method, TRAPS) {
+void Method::link_method(const methodHandle& h_method, TRAPS) {
   // If the code cache is full, we may reenter this function for the
   // leftover methods that weren't linked.
   if (_i2i_entry != NULL) return;
@@ -1178,7 +1175,7 @@
 
 Klass* Method::check_non_bcp_klass(Klass* klass) {
   if (klass != NULL && klass->class_loader() != NULL) {
-    if (klass->oop_is_objArray())
+    if (klass->is_objArray_klass())
       klass = ObjArrayKlass::cast(klass)->bottom_klass();
     return klass;
   }
@@ -1305,6 +1302,73 @@
   return vmSymbols::find_sid(klass_name);
 }
 
+static bool is_unsafe_alias(vmSymbols::SID name_id) {
+  // All 70 intrinsic candidate methods from sun.misc.Unsafe in 1.8.
+  // Some have the same method name but different signature, e.g.
+  // getByte(long), getByte(Object,long)
+  switch (name_id) {
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(allocateInstance_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(copyMemory_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(loadFence_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(storeFence_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(fullFence_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getObject_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getBoolean_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getByte_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getShort_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getChar_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getInt_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getLong_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloat_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getDouble_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putObject_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putBoolean_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putByte_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putShort_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putChar_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putInt_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putLong_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloat_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putDouble_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getObjectVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getBooleanVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getByteVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getShortVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getCharVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getIntVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getLongVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloatVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getDoubleVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putObjectVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putBooleanVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putByteVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putShortVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putCharVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putIntVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putLongVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloatVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putDoubleVolatile_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getAddress_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putAddress_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapObject_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapLong_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapInt_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedObject_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedLong_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedInt_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddInt_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddLong_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetInt_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetLong_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetObject_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(park_name):
+    case vmSymbols::VM_SYMBOL_ENUM_NAME(unpark_name):
+      return true;
+  }
+
+  return false;
+}
+
 void Method::init_intrinsic_id() {
   assert(_intrinsic_id == vmIntrinsics::_none, "do this just once");
   const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte));
@@ -1357,6 +1421,14 @@
     if (is_static() != MethodHandles::is_signature_polymorphic_static(id))
       id = vmIntrinsics::_none;
     break;
+
+  case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Unsafe):
+    // Map sun.misc.Unsafe to jdk.internal.misc.Unsafe
+    if (!is_unsafe_alias(name_id))  break;
+    // pretend it is the corresponding method in the internal Unsafe class:
+    klass_id = vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_misc_Unsafe);
+    id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
+    break;
   }
 
   if (id != vmIntrinsics::_none) {
--- a/hotspot/src/share/vm/oops/method.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/method.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -393,7 +393,7 @@
   bool was_executed_more_than(int n);
   bool was_never_executed()                      { return !was_executed_more_than(0); }
 
-  static void build_interpreter_method_data(methodHandle method, TRAPS);
+  static void build_interpreter_method_data(const methodHandle& method, TRAPS);
 
   static MethodCounters* build_method_counters(Method* m, TRAPS);
 
@@ -435,7 +435,7 @@
   address get_c2i_unverified_entry();
   AdapterHandlerEntry* adapter() {  return _adapter; }
   // setup entry points
-  void link_method(methodHandle method, TRAPS);
+  void link_method(const methodHandle& method, TRAPS);
   // clear entry points. Used by sharing code
   void unlink_method();
 
--- a/hotspot/src/share/vm/oops/methodData.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -708,7 +708,7 @@
 // A MethodData* holds information which has been collected about
 // a method.
 
-MethodData* MethodData::allocate(ClassLoaderData* loader_data, methodHandle method, TRAPS) {
+MethodData* MethodData::allocate(ClassLoaderData* loader_data, const methodHandle& method, TRAPS) {
   int size = MethodData::compute_allocation_size_in_words(method);
 
   return new (loader_data, size, false, MetaspaceObj::MethodDataType, THREAD)
@@ -898,7 +898,7 @@
 
 // Compute the size of the MethodData* necessary to store
 // profiling information about a given method.  Size is in bytes.
-int MethodData::compute_allocation_size_in_bytes(methodHandle method) {
+int MethodData::compute_allocation_size_in_bytes(const methodHandle& method) {
   int data_size = 0;
   BytecodeStream stream(method);
   Bytecodes::Code c;
@@ -931,7 +931,7 @@
 
 // Compute the size of the MethodData* necessary to store
 // profiling information about a given method.  Size is in words
-int MethodData::compute_allocation_size_in_words(methodHandle method) {
+int MethodData::compute_allocation_size_in_words(const methodHandle& method) {
   int byte_size = compute_allocation_size_in_bytes(method);
   int word_size = align_size_up(byte_size, BytesPerWord) / BytesPerWord;
   return align_object_size(word_size);
@@ -1102,7 +1102,9 @@
     return new VirtualCallTypeData(this);
   case DataLayout::parameters_type_data_tag:
     return new ParametersTypeData(this);
-  };
+  case DataLayout::speculative_trap_data_tag:
+    return new SpeculativeTrapData(this);
+  }
 }
 
 // Iteration over data.
@@ -1129,7 +1131,7 @@
 }
 
 // Initialize the MethodData* corresponding to a given method.
-MethodData::MethodData(methodHandle method, int size, TRAPS)
+MethodData::MethodData(const methodHandle& method, int size, TRAPS)
   : _extra_data_lock(Monitor::leaf, "MDO extra data lock"),
     _parameters_type_data_di(parameters_uninitialized) {
   // Set the method back-pointer.
@@ -1513,7 +1515,7 @@
   // not yet implemented.
 }
 
-bool MethodData::profile_jsr292(methodHandle m, int bci) {
+bool MethodData::profile_jsr292(const methodHandle& m, int bci) {
   if (m->is_compiled_lambda_form()) {
     return true;
   }
@@ -1538,7 +1540,7 @@
   return profile_arguments_flag() == type_profile_all;
 }
 
-bool MethodData::profile_arguments_for_invoke(methodHandle m, int bci) {
+bool MethodData::profile_arguments_for_invoke(const methodHandle& m, int bci) {
   if (!profile_arguments()) {
     return false;
   }
@@ -1567,7 +1569,7 @@
   return profile_return_flag() == type_profile_all;
 }
 
-bool MethodData::profile_return_for_invoke(methodHandle m, int bci) {
+bool MethodData::profile_return_for_invoke(const methodHandle& m, int bci) {
   if (!profile_return()) {
     return false;
   }
@@ -1596,7 +1598,7 @@
   return profile_parameters_flag() == type_profile_all;
 }
 
-bool MethodData::profile_parameters_for_method(methodHandle m) {
+bool MethodData::profile_parameters_for_method(const methodHandle& m) {
   if (!profile_parameters()) {
     return false;
   }
--- a/hotspot/src/share/vm/oops/methodData.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -535,6 +535,7 @@
 //
 // A BitData holds a flag or two in its header.
 class BitData : public ProfileData {
+  friend class VMStructs;
 protected:
   enum {
     // null_seen:
@@ -603,6 +604,7 @@
 //
 // A CounterData corresponds to a simple counter.
 class CounterData : public BitData {
+  friend class VMStructs;
 protected:
   enum {
     count_off,
@@ -667,6 +669,7 @@
 // plus a data displacement, used for realigning the data pointer to
 // the corresponding target bci.
 class JumpData : public ProfileData {
+  friend class VMStructs;
 protected:
   enum {
     taken_off_set,
@@ -1173,6 +1176,7 @@
 // that the check is reached, and a series of (Klass*, count) pairs
 // which are used to store a type profile for the receiver of the check.
 class ReceiverTypeData : public CounterData {
+  friend class VMStructs;
 protected:
   enum {
 #if INCLUDE_JVMCI
@@ -1678,6 +1682,7 @@
 // It consists of taken and not_taken counts as well as a data displacement
 // for the taken case.
 class BranchData : public JumpData {
+  friend class VMStructs;
 protected:
   enum {
     not_taken_off_set = jump_cell_count,
@@ -1754,6 +1759,7 @@
 // not have a statically known size.  It consists of an array length
 // and an array start.
 class ArrayData : public ProfileData {
+  friend class VMStructs;
 protected:
   friend class DataLayout;
 
@@ -1831,6 +1837,7 @@
 // of (count, displacement) pairs, which count the number of times each
 // case was taken and specify the data displacment for each branch target.
 class MultiBranchData : public ArrayData {
+  friend class VMStructs;
 protected:
   enum {
     default_count_off_set,
@@ -2145,9 +2152,9 @@
 
   Mutex _extra_data_lock;
 
-  MethodData(methodHandle method, int size, TRAPS);
+  MethodData(const methodHandle& method, int size, TRAPS);
 public:
-  static MethodData* allocate(ClassLoaderData* loader_data, methodHandle method, TRAPS);
+  static MethodData* allocate(ClassLoaderData* loader_data, const methodHandle& method, TRAPS);
   MethodData() : _extra_data_lock(Monitor::leaf, "MDO extra data lock") {}; // For ciMethodData
 
   bool is_methodData() const volatile { return true; }
@@ -2283,13 +2290,13 @@
     type_profile_all = 2
   };
 
-  static bool profile_jsr292(methodHandle m, int bci);
+  static bool profile_jsr292(const methodHandle& m, int bci);
   static int profile_arguments_flag();
   static bool profile_all_arguments();
-  static bool profile_arguments_for_invoke(methodHandle m, int bci);
+  static bool profile_arguments_for_invoke(const methodHandle& m, int bci);
   static int profile_return_flag();
   static bool profile_all_return();
-  static bool profile_return_for_invoke(methodHandle m, int bci);
+  static bool profile_return_for_invoke(const methodHandle& m, int bci);
   static int profile_parameters_flag();
   static bool profile_parameters_jsr292_only();
   static bool profile_all_parameters();
@@ -2304,8 +2311,8 @@
   }
 
   // Compute the size of a MethodData* before it is created.
-  static int compute_allocation_size_in_bytes(methodHandle method);
-  static int compute_allocation_size_in_words(methodHandle method);
+  static int compute_allocation_size_in_bytes(const methodHandle& method);
+  static int compute_allocation_size_in_words(const methodHandle& method);
   static int compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps);
 
   // Determine if a given bytecode can have profile information.
@@ -2589,7 +2596,7 @@
   void verify_on(outputStream* st);
   void verify_data_on(outputStream* st);
 
-  static bool profile_parameters_for_method(methodHandle m);
+  static bool profile_parameters_for_method(const methodHandle& m);
   static bool profile_arguments();
   static bool profile_arguments_jsr292_only();
   static bool profile_return();
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -102,7 +102,7 @@
 
   // Create type name for klass.
   Symbol* name = NULL;
-  if (!element_klass->oop_is_instance() ||
+  if (!element_klass->is_instance_klass() ||
       (name = InstanceKlass::cast(element_klass())->array_name()) == NULL) {
 
     ResourceMark rm(THREAD);
@@ -111,17 +111,17 @@
     char *new_str = NEW_RESOURCE_ARRAY(char, len + 4);
     int idx = 0;
     new_str[idx++] = '[';
-    if (element_klass->oop_is_instance()) { // it could be an array or simple type
+    if (element_klass->is_instance_klass()) { // it could be an array or simple type
       new_str[idx++] = 'L';
     }
     memcpy(&new_str[idx], name_str, len * sizeof(char));
     idx += len;
-    if (element_klass->oop_is_instance()) {
+    if (element_klass->is_instance_klass()) {
       new_str[idx++] = ';';
     }
     new_str[idx++] = '\0';
     name = SymbolTable::new_permanent_symbol(new_str, CHECK_0);
-    if (element_klass->oop_is_instance()) {
+    if (element_klass->is_instance_klass()) {
       InstanceKlass* ik = InstanceKlass::cast(element_klass());
       ik->set_array_name(name);
     }
@@ -150,18 +150,18 @@
   name->decrement_refcount();
 
   Klass* bk;
-  if (element_klass->oop_is_objArray()) {
+  if (element_klass->is_objArray_klass()) {
     bk = ObjArrayKlass::cast(element_klass())->bottom_klass();
   } else {
     bk = element_klass();
   }
-  assert(bk != NULL && (bk->oop_is_instance() || bk->oop_is_typeArray()), "invalid bottom klass");
+  assert(bk != NULL && (bk->is_instance_klass() || bk->is_typeArray_klass()), "invalid bottom klass");
   this->set_bottom_klass(bk);
   this->set_class_loader_data(bk->class_loader_data());
 
   this->set_layout_helper(array_layout_helper(T_OBJECT));
-  assert(this->oop_is_array(), "sanity");
-  assert(this->oop_is_objArray(), "sanity");
+  assert(this->is_array_klass(), "sanity");
+  assert(this->is_objArray_klass(), "sanity");
 }
 
 int ObjArrayKlass::oop_size(oop obj) const {
@@ -336,7 +336,7 @@
         ak->set_lower_dimension(this);
         OrderAccess::storestore();
         set_higher_dimension(ak);
-        assert(ak->oop_is_objArray(), "incorrect initialization of ObjArrayKlass");
+        assert(ak->is_objArray_klass(), "incorrect initialization of ObjArrayKlass");
       }
     }
   } else {
@@ -386,7 +386,7 @@
 }
 
 bool ObjArrayKlass::compute_is_subtype_of(Klass* k) {
-  if (!k->oop_is_objArray())
+  if (!k->is_objArray_klass())
     return ArrayKlass::compute_is_subtype_of(k);
 
   ObjArrayKlass* oak = ObjArrayKlass::cast(k);
@@ -484,7 +484,7 @@
   guarantee(element_klass()->is_klass(), "should be klass");
   guarantee(bottom_klass()->is_klass(), "should be klass");
   Klass* bk = bottom_klass();
-  guarantee(bk->oop_is_instance() || bk->oop_is_typeArray(),  "invalid bottom klass");
+  guarantee(bk->is_instance_klass() || bk->is_typeArray_klass(),  "invalid bottom klass");
 }
 
 void ObjArrayKlass::oop_verify_on(oop obj, outputStream* st) {
--- a/hotspot/src/share/vm/oops/objArrayKlass.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +60,7 @@
   bool can_be_primary_super_slow() const;
   GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
   bool compute_is_subtype_of(Klass* k);
-  bool oop_is_objArray_slow()  const  { return true; }
+  DEBUG_ONLY(bool is_objArray_klass_slow()  const  { return true; })
   int oop_size(oop obj) const;
 
   // Allocation
@@ -91,8 +91,8 @@
  public:
   // Casting from Klass*
   static ObjArrayKlass* cast(Klass* k) {
-    assert(k->oop_is_objArray(), "cast to ObjArrayKlass");
-    return (ObjArrayKlass*) k;
+    assert(k->is_objArray_klass(), "cast to ObjArrayKlass");
+    return static_cast<ObjArrayKlass*>(k);
   }
 
   // Sizing
--- a/hotspot/src/share/vm/oops/oop.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/oop.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -129,9 +129,6 @@
 
 // type test operations that doesn't require inclusion of oop.inline.hpp.
 bool oopDesc::is_instance_noinline()          const { return is_instance();            }
-bool oopDesc::is_instanceMirror_noinline()    const { return is_instanceMirror();      }
-bool oopDesc::is_instanceClassLoader_noline() const { return is_instanceClassLoader(); }
-bool oopDesc::is_instanceRef_noline()         const { return is_instanceRef();         }
 bool oopDesc::is_array_noinline()             const { return is_array();               }
 bool oopDesc::is_objArray_noinline()          const { return is_objArray();            }
 bool oopDesc::is_typeArray_noinline()         const { return is_typeArray();           }
--- a/hotspot/src/share/vm/oops/oop.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/oop.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -110,18 +110,12 @@
 
   // type test operations (inlined in oop.inline.hpp)
   bool is_instance()            const;
-  bool is_instanceMirror()      const;
-  bool is_instanceClassLoader() const;
-  bool is_instanceRef()         const;
   bool is_array()               const;
   bool is_objArray()            const;
   bool is_typeArray()           const;
 
   // type test operations that don't require inclusion of oop.inline.hpp.
   bool is_instance_noinline()          const;
-  bool is_instanceMirror_noinline()    const;
-  bool is_instanceClassLoader_noline() const;
-  bool is_instanceRef_noline()         const;
   bool is_array_noinline()             const;
   bool is_objArray_noinline()          const;
   bool is_typeArray_noinline()         const;
--- a/hotspot/src/share/vm/oops/oop.inline.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -127,27 +127,12 @@
 inline bool oopDesc::is_a(Klass* k)        const { return klass()->is_subtype_of(k); }
 
 inline bool oopDesc::is_instance() const {
-  return klass()->oop_is_instance();
-}
-
-inline bool oopDesc::is_instanceClassLoader() const {
-  Klass* k = klass();
-  return k->oop_is_instance() && InstanceKlass::cast(k)->is_class_loader_instance_klass();
+  return klass()->is_instance_klass();
 }
 
-inline bool oopDesc::is_instanceMirror() const {
-  Klass* k = klass();
-  return k->oop_is_instance() && InstanceKlass::cast(k)->is_mirror_instance_klass();
-}
-
-inline bool oopDesc::is_instanceRef() const {
-  Klass* k = klass();
-  return k->oop_is_instance() && InstanceKlass::cast(k)->is_reference_instance_klass();
-}
-
-inline bool oopDesc::is_array()               const { return klass()->oop_is_array(); }
-inline bool oopDesc::is_objArray()            const { return klass()->oop_is_objArray(); }
-inline bool oopDesc::is_typeArray()           const { return klass()->oop_is_typeArray(); }
+inline bool oopDesc::is_array()               const { return klass()->is_array_klass(); }
+inline bool oopDesc::is_objArray()            const { return klass()->is_objArray_klass(); }
+inline bool oopDesc::is_typeArray()           const { return klass()->is_typeArray_klass(); }
 
 inline void*     oopDesc::field_base(int offset)        const { return (void*)&((char*)this)[offset]; }
 
@@ -724,7 +709,7 @@
 
 inline void oopDesc::pc_update_contents() {
   Klass* k = klass();
-  if (!k->oop_is_typeArray()) {
+  if (!k->is_typeArray_klass()) {
     // It might contain oops beyond the header, so take the virtual call.
     k->oop_pc_update_pointers(this);
   }
@@ -733,7 +718,7 @@
 
 inline void oopDesc::ps_push_contents(PSPromotionManager* pm) {
   Klass* k = klass();
-  if (!k->oop_is_typeArray()) {
+  if (!k->is_typeArray_klass()) {
     // It might contain oops beyond the header, so take the virtual call.
     k->oop_ps_push_contents(this, pm);
   }
--- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -43,7 +43,7 @@
 #include "utilities/macros.hpp"
 
 bool TypeArrayKlass::compute_is_subtype_of(Klass* k) {
-  if (!k->oop_is_typeArray()) {
+  if (!k->is_typeArray_klass()) {
     return ArrayKlass::compute_is_subtype_of(k);
   }
 
@@ -86,8 +86,8 @@
 
 TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name) {
   set_layout_helper(array_layout_helper(type));
-  assert(oop_is_array(), "sanity");
-  assert(oop_is_typeArray(), "sanity");
+  assert(is_array_klass(), "sanity");
+  assert(is_typeArray_klass(), "sanity");
 
   set_max_length(arrayOopDesc::max_array_length(type));
   assert(size() >= TypeArrayKlass::header_size(), "bad size");
@@ -181,7 +181,7 @@
         h_ak->set_lower_dimension(this);
         OrderAccess::storestore();
         set_higher_dimension(h_ak);
-        assert(h_ak->oop_is_objArray(), "incorrect initialization of ObjArrayKlass");
+        assert(h_ak->is_objArray_klass(), "incorrect initialization of ObjArrayKlass");
       }
     }
   } else {
--- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +47,7 @@
   void set_max_length(jint m)           { _max_length = m;    }
 
   // testers
-  bool oop_is_typeArray_slow() const    { return true; }
+  DEBUG_ONLY(bool is_typeArray_klass_slow() const  { return true; })
 
   // klass allocation
   static TypeArrayKlass* create_klass(BasicType type, const char* name_str,
@@ -122,8 +122,8 @@
  public:
   // Casting from Klass*
   static TypeArrayKlass* cast(Klass* k) {
-    assert(k->oop_is_typeArray(), "cast to TypeArrayKlass");
-    return (TypeArrayKlass*) k;
+    assert(k->is_typeArray_klass(), "cast to TypeArrayKlass");
+    return static_cast<TypeArrayKlass*>(k);
   }
 
   // Naming
--- a/hotspot/src/share/vm/oops/typeArrayOop.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -48,47 +48,47 @@
 
  public:
   jbyte* byte_at_addr(int which) const {
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return &byte_base()[which];
   }
 
   jboolean* bool_at_addr(int which) const {
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return &bool_base()[which];
   }
 
   jchar* char_at_addr(int which) const {
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return &char_base()[which];
   }
 
   jint* int_at_addr(int which) const {
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return &int_base()[which];
   }
 
   jshort* short_at_addr(int which) const {
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return &short_base()[which];
   }
 
   jushort* ushort_at_addr(int which) const {  // for field descriptor arrays
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return (jushort*) &short_base()[which];
   }
 
   jlong* long_at_addr(int which) const {
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return &long_base()[which];
   }
 
   jfloat* float_at_addr(int which) const {
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return &float_base()[which];
   }
 
   jdouble* double_at_addr(int which) const {
-    assert(is_within_bounds(which), "index out of bounds");
+    assert(is_within_bounds(which), "index %d out of bounds %d", which, length());
     return &double_base()[which];
   }
 
--- a/hotspot/src/share/vm/opto/c2compiler.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -158,7 +158,7 @@
   Compile::print_timers();
 }
 
-bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) {
+bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virtual) {
   vmIntrinsics::ID id = method->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
 
@@ -181,12 +181,25 @@
   }
 
   switch (id) {
-  case vmIntrinsics::_compareTo:
+  case vmIntrinsics::_compressStringC:
+  case vmIntrinsics::_compressStringB:
+    if (!Matcher::has_match_rule(Op_StrCompressedCopy)) return false;
+    break;
+  case vmIntrinsics::_inflateStringC:
+  case vmIntrinsics::_inflateStringB:
+    if (!Matcher::has_match_rule(Op_StrInflatedCopy)) return false;
+    break;
+  case vmIntrinsics::_compareToL:
+  case vmIntrinsics::_compareToU:
+  case vmIntrinsics::_compareToLU:
+  case vmIntrinsics::_compareToUL:
     if (!Matcher::match_rule_supported(Op_StrComp)) return false;
     break;
-  case vmIntrinsics::_equals:
+  case vmIntrinsics::_equalsL:
+  case vmIntrinsics::_equalsU:
     if (!Matcher::match_rule_supported(Op_StrEquals)) return false;
     break;
+  case vmIntrinsics::_equalsB:
   case vmIntrinsics::_equalsC:
     if (!Matcher::match_rule_supported(Op_AryEq)) return false;
     break;
@@ -194,8 +207,12 @@
     if (StubRoutines::unsafe_arraycopy() == NULL) return false;
     break;
   case vmIntrinsics::_encodeISOArray:
+  case vmIntrinsics::_encodeByteISOArray:
     if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return false;
     break;
+  case vmIntrinsics::_hasNegatives:
+    if (!Matcher::match_rule_supported(Op_HasNegatives))  return false;
+    break;
   case vmIntrinsics::_bitCount_i:
     if (!Matcher::match_rule_supported(Op_PopCountI)) return false;
     break;
@@ -302,7 +319,17 @@
   case vmIntrinsics::_min:
   case vmIntrinsics::_max:
   case vmIntrinsics::_arraycopy:
-  case vmIntrinsics::_indexOf:
+  case vmIntrinsics::_indexOfL:
+  case vmIntrinsics::_indexOfU:
+  case vmIntrinsics::_indexOfUL:
+  case vmIntrinsics::_indexOfIL:
+  case vmIntrinsics::_indexOfIU:
+  case vmIntrinsics::_indexOfIUL:
+  case vmIntrinsics::_indexOfU_char:
+  case vmIntrinsics::_toBytesStringU:
+  case vmIntrinsics::_getCharsStringU:
+  case vmIntrinsics::_getCharStringU:
+  case vmIntrinsics::_putCharStringU:
   case vmIntrinsics::_getObject:
   case vmIntrinsics::_getBoolean:
   case vmIntrinsics::_getByte:
--- a/hotspot/src/share/vm/opto/c2compiler.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/c2compiler.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,13 +57,13 @@
   // possible for only a limited set of available intrinsics whereas
   // a non-virtual dispatch is possible for all available intrinsics.)
   // Return false otherwise.
-  virtual bool is_intrinsic_supported(methodHandle method) {
+  virtual bool is_intrinsic_supported(const methodHandle& method) {
     return is_intrinsic_supported(method, false);
   }
 
   // Check if the compiler supports an intrinsic for 'method' given the
   // the dispatch mode specified by the 'is_virtual' parameter.
-  virtual bool is_intrinsic_supported(methodHandle method, bool is_virtual);
+  virtual bool is_intrinsic_supported(const methodHandle& method, bool is_virtual);
 
   // Initial size of the code buffer (may be increased at runtime)
   static int initial_code_buffer_size();
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -671,7 +671,7 @@
                                            &exact_receiver);
 
   SafePointNode* slow_map = NULL;
-  JVMState* slow_jvms;
+  JVMState* slow_jvms = NULL;
   { PreserveJVMState pjvms(&kit);
     kit.set_control(slow_ctl);
     if (!kit.stopped()) {
--- a/hotspot/src/share/vm/opto/classes.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/classes.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -136,6 +136,7 @@
 macro(FastUnlock)
 macro(Goto)
 macro(Halt)
+macro(HasNegatives)
 macro(If)
 macro(IfFalse)
 macro(IfTrue)
@@ -246,8 +247,11 @@
 macro(StoreN)
 macro(StoreNKlass)
 macro(StrComp)
+macro(StrCompressedCopy)
 macro(StrEquals)
 macro(StrIndexOf)
+macro(StrIndexOfChar)
+macro(StrInflatedCopy)
 macro(SubD)
 macro(SubF)
 macro(SubI)
--- a/hotspot/src/share/vm/opto/compile.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -3762,7 +3762,7 @@
   MacroAssembler _masm(&cb);
   for (int i = 0; i < _constants.length(); i++) {
     Constant con = _constants.at(i);
-    address constant_addr;
+    address constant_addr = NULL;
     switch (con.type()) {
     case T_LONG:   constant_addr = _masm.long_constant(  con.get_jlong()  ); break;
     case T_FLOAT:  constant_addr = _masm.float_constant( con.get_jfloat() ); break;
--- a/hotspot/src/share/vm/opto/compile.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -89,7 +89,7 @@
 typedef unsigned int node_idx_t;
 class NodeCloneInfo {
  private:
-  uint64_t  _idx_clone_orig;
+  uint64_t _idx_clone_orig;
  public:
 
   void set_idx(node_idx_t idx) {
@@ -98,17 +98,17 @@
   node_idx_t idx() const { return (node_idx_t)(_idx_clone_orig & 0xFFFFFFFF); }
 
   void set_gen(int generation) {
-    uint64_t  g = (uint64_t)generation << 32;
+    uint64_t g = (uint64_t)generation << 32;
     _idx_clone_orig = _idx_clone_orig & 0xFFFFFFFF | g;
   }
   int gen() const { return (int)(_idx_clone_orig >> 32); }
 
-  void set(uint64_t x) {  _idx_clone_orig = x; }
-  void set(node_idx_t x, int g) {  set_idx(x); set_gen(g); }
+  void set(uint64_t x) { _idx_clone_orig = x; }
+  void set(node_idx_t x, int g) { set_idx(x); set_gen(g); }
   uint64_t get() const { return _idx_clone_orig; }
 
   NodeCloneInfo(uint64_t idx_clone_orig) : _idx_clone_orig(idx_clone_orig) {}
-  NodeCloneInfo(node_idx_t x, int g) {set(x, g);}
+  NodeCloneInfo(node_idx_t x, int g) : _idx_clone_orig(0) { set(x, g); }
 
   void dump() const;
 };
--- a/hotspot/src/share/vm/opto/escape.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -560,9 +560,13 @@
       break;
     }
     case Op_AryEq:
+    case Op_HasNegatives:
     case Op_StrComp:
     case Op_StrEquals:
     case Op_StrIndexOf:
+    case Op_StrIndexOfChar:
+    case Op_StrInflatedCopy:
+    case Op_StrCompressedCopy:
     case Op_EncodeISOArray: {
       add_local_var(n, PointsToNode::ArgEscape);
       delayed_worklist->push(n); // Process it later.
@@ -743,11 +747,15 @@
       ELSE_FAIL("Op_StoreP");
     }
     case Op_AryEq:
+    case Op_HasNegatives:
     case Op_StrComp:
     case Op_StrEquals:
     case Op_StrIndexOf:
+    case Op_StrIndexOfChar:
+    case Op_StrInflatedCopy:
+    case Op_StrCompressedCopy:
     case Op_EncodeISOArray: {
-      // char[] arrays passed to string intrinsic do not escape but
+      // char[]/byte[] arrays passed to string intrinsic do not escape but
       // they are not scalar replaceable. Adjust escape state for them.
       // Start from in(2) edge since in(1) is memory edge.
       for (uint i = 2; i < n->req(); i++) {
@@ -2722,17 +2730,34 @@
       if (mem->is_LoadStore()) {
         adr = mem->in(MemNode::Address);
       } else {
-        assert(mem->Opcode() == Op_EncodeISOArray, "sanity");
+        assert(mem->Opcode() == Op_EncodeISOArray ||
+               mem->Opcode() == Op_StrCompressedCopy, "sanity");
         adr = mem->in(3); // Memory edge corresponds to destination array
       }
       const Type *at = igvn->type(adr);
       if (at != Type::TOP) {
-        assert (at->isa_ptr() != NULL, "pointer type required.");
+        assert(at->isa_ptr() != NULL, "pointer type required.");
         int idx = C->get_alias_index(at->is_ptr());
-        assert(idx != alias_idx, "Object is not scalar replaceable if a LoadStore node access its field");
-        break;
+        if (idx == alias_idx) {
+          // Assert in debug mode
+          assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field");
+          break; // In product mode return SCMemProj node
+        }
       }
       result = mem->in(MemNode::Memory);
+    } else if (result->Opcode() == Op_StrInflatedCopy) {
+      Node* adr = result->in(3); // Memory edge corresponds to destination array
+      const Type *at = igvn->type(adr);
+      if (at != Type::TOP) {
+        assert(at->isa_ptr() != NULL, "pointer type required.");
+        int idx = C->get_alias_index(at->is_ptr());
+        if (idx == alias_idx) {
+          // Assert in debug mode
+          assert(false, "Object is not scalar replaceable if a StrInflatedCopy node accesses its field");
+          break; // In product mode return SCMemProj node
+        }
+      }
+      result = result->in(MemNode::Memory);
     }
   }
   if (result->is_Phi()) {
@@ -3096,10 +3121,15 @@
         }
       } else {
         uint op = use->Opcode();
-        if (!(op == Op_CmpP || op == Op_Conv2B ||
+        if ((use->in(MemNode::Memory) == n) &&
+            (op == Op_StrCompressedCopy || op == Op_StrInflatedCopy)) {
+          // They overwrite memory edge corresponding to destination array,
+          memnode_worklist.append_if_missing(use);
+        } else if (!(op == Op_CmpP || op == Op_Conv2B ||
               op == Op_CastP2X || op == Op_StoreCM ||
-              op == Op_FastLock || op == Op_AryEq || op == Op_StrComp ||
-              op == Op_StrEquals || op == Op_StrIndexOf)) {
+              op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || op == Op_HasNegatives ||
+              op == Op_StrCompressedCopy || op == Op_StrInflatedCopy ||
+              op == Op_StrEquals || op == Op_StrIndexOf || op == Op_StrIndexOfChar)) {
           n->dump();
           use->dump();
           assert(false, "EA: missing allocation reference path");
@@ -3161,7 +3191,8 @@
       n = n->as_MemBar()->proj_out(TypeFunc::Memory);
       if (n == NULL)
         continue;
-    } else if (n->Opcode() == Op_EncodeISOArray) {
+    } else if (n->Opcode() == Op_StrCompressedCopy ||
+               n->Opcode() == Op_EncodeISOArray) {
       // get the memory projection
       n = n->find_out_with(Op_SCMemProj);
       assert(n->Opcode() == Op_SCMemProj, "memory projection required");
@@ -3216,11 +3247,16 @@
         }
       } else {
         uint op = use->Opcode();
-        if (!(op == Op_StoreCM ||
+        if ((use->in(MemNode::Memory) == n) &&
+            (op == Op_StrCompressedCopy || op == Op_StrInflatedCopy)) {
+          // They overwrite memory edge corresponding to destination array,
+          memnode_worklist.append_if_missing(use);
+        } else if (!(op == Op_StoreCM ||
               (op == Op_CallLeaf && use->as_CallLeaf()->_name != NULL &&
                strcmp(use->as_CallLeaf()->_name, "g1_wb_pre") == 0) ||
-              op == Op_AryEq || op == Op_StrComp ||
-              op == Op_StrEquals || op == Op_StrIndexOf)) {
+              op == Op_AryEq || op == Op_StrComp || op == Op_HasNegatives ||
+              op == Op_StrCompressedCopy || op == Op_StrInflatedCopy ||
+              op == Op_StrEquals || op == Op_StrIndexOf || op == Op_StrIndexOfChar)) {
           n->dump();
           use->dump();
           assert(false, "EA: missing memory path");
--- a/hotspot/src/share/vm/opto/gcm.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/gcm.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -504,8 +504,12 @@
          "String equals is a 'load' that does not conflict with any stores");
   assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrIndexOf),
          "String indexOf is a 'load' that does not conflict with any stores");
+  assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_StrIndexOfChar),
+         "String indexOfChar is a 'load' that does not conflict with any stores");
   assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_AryEq),
-         "Arrays equals is a 'load' that do not conflict with any stores");
+         "Arrays equals is a 'load' that does not conflict with any stores");
+  assert(load_alias_idx || (load->is_Mach() && load->as_Mach()->ideal_Opcode() == Op_HasNegatives),
+         "HasNegatives is a 'load' that does not conflict with any stores");
 
   if (!C->alias_type(load_alias_idx)->is_rewritable()) {
     // It is impossible to spoil this load by putting stores before it,
--- a/hotspot/src/share/vm/opto/generateOptoStub.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -261,7 +261,7 @@
 
   //-----------------------------
   // If this is a normal subroutine return, issue the return and be done.
-  Node *ret;
+  Node *ret = NULL;
   switch( is_fancy_jump ) {
   case 0:                       // Make a return instruction
     // Return to caller, free any space for return address
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -4266,35 +4266,11 @@
 #undef __
 
 
-
-Node* GraphKit::load_String_offset(Node* ctrl, Node* str) {
-  if (java_lang_String::has_offset_field()) {
-    int offset_offset = java_lang_String::offset_offset_in_bytes();
-    const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
-                                                       false, NULL, 0);
-    const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
-    int offset_field_idx = C->get_alias_index(offset_field_type);
-    return make_load(ctrl,
-                     basic_plus_adr(str, str, offset_offset),
-                     TypeInt::INT, T_INT, offset_field_idx, MemNode::unordered);
-  } else {
-    return intcon(0);
-  }
-}
-
 Node* GraphKit::load_String_length(Node* ctrl, Node* str) {
-  if (java_lang_String::has_count_field()) {
-    int count_offset = java_lang_String::count_offset_in_bytes();
-    const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
-                                                       false, NULL, 0);
-    const TypePtr* count_field_type = string_type->add_offset(count_offset);
-    int count_field_idx = C->get_alias_index(count_field_type);
-    return make_load(ctrl,
-                     basic_plus_adr(str, str, count_offset),
-                     TypeInt::INT, T_INT, count_field_idx, MemNode::unordered);
-  } else {
-    return load_array_length(load_String_value(ctrl, str));
-  }
+  Node* len = load_array_length(load_String_value(ctrl, str));
+  Node* coder = load_String_coder(ctrl, str);
+  // Divide length by 2 if coder is UTF16
+  return _gvn.transform(new RShiftINode(len, coder));
 }
 
 Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
@@ -4302,9 +4278,9 @@
   const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
                                                      false, NULL, 0);
   const TypePtr* value_field_type = string_type->add_offset(value_offset);
-  const TypeAryPtr*  value_type = TypeAryPtr::make(TypePtr::NotNull,
-                                                   TypeAry::make(TypeInt::CHAR,TypeInt::POS),
-                                                   ciTypeArrayKlass::make(T_CHAR), true, 0);
+  const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
+                                                  TypeAry::make(TypeInt::BYTE, TypeInt::POS),
+                                                  ciTypeArrayKlass::make(T_BYTE), true, 0);
   int value_field_idx = C->get_alias_index(value_field_type);
   Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset),
                          value_type, T_OBJECT, value_field_idx, MemNode::unordered);
@@ -4315,14 +4291,21 @@
   return load;
 }
 
-void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) {
-  int offset_offset = java_lang_String::offset_offset_in_bytes();
-  const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
-                                                     false, NULL, 0);
-  const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
-  int offset_field_idx = C->get_alias_index(offset_field_type);
-  store_to_memory(ctrl, basic_plus_adr(str, offset_offset),
-                  value, T_INT, offset_field_idx, MemNode::unordered);
+Node* GraphKit::load_String_coder(Node* ctrl, Node* str) {
+  if (java_lang_String::has_coder_field()) {
+    if (!CompactStrings) {
+      return intcon(java_lang_String::CODER_UTF16);
+    }
+    int coder_offset = java_lang_String::coder_offset_in_bytes();
+    const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+                                                       false, NULL, 0);
+    const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
+    int coder_field_idx = C->get_alias_index(coder_field_type);
+    return make_load(ctrl, basic_plus_adr(str, str, coder_offset),
+                     TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered);
+  } else {
+    return intcon(0); // false
+  }
 }
 
 void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
@@ -4330,19 +4313,76 @@
   const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
                                                      false, NULL, 0);
   const TypePtr* value_field_type = string_type->add_offset(value_offset);
-
   store_oop_to_object(ctrl, str,  basic_plus_adr(str, value_offset), value_field_type,
-      value, TypeAryPtr::CHARS, T_OBJECT, MemNode::unordered);
+      value, TypeAryPtr::BYTES, T_OBJECT, MemNode::unordered);
 }
 
-void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
-  int count_offset = java_lang_String::count_offset_in_bytes();
+void GraphKit::store_String_coder(Node* ctrl, Node* str, Node* value) {
+  int coder_offset = java_lang_String::coder_offset_in_bytes();
   const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
                                                      false, NULL, 0);
-  const TypePtr* count_field_type = string_type->add_offset(count_offset);
-  int count_field_idx = C->get_alias_index(count_field_type);
-  store_to_memory(ctrl, basic_plus_adr(str, count_offset),
-                  value, T_INT, count_field_idx, MemNode::unordered);
+  const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
+  int coder_field_idx = C->get_alias_index(coder_field_type);
+  store_to_memory(ctrl, basic_plus_adr(str, coder_offset),
+                  value, T_BYTE, coder_field_idx, MemNode::unordered);
+}
+
+Node* GraphKit::compress_string(Node* src, Node* dst, Node* count) {
+  assert(Matcher::match_rule_supported(Op_StrCompressedCopy), "Intrinsic not supported");
+  uint idx = C->get_alias_index(TypeAryPtr::BYTES);
+  StrCompressedCopyNode* str = new StrCompressedCopyNode(control(), memory(idx), src, dst, count);
+  Node* res_mem = _gvn.transform(new SCMemProjNode(str));
+  set_memory(res_mem, idx);
+  return str;
+}
+
+void GraphKit::inflate_string(Node* src, Node* dst, Node* count) {
+  assert(Matcher::match_rule_supported(Op_StrInflatedCopy), "Intrinsic not supported");
+  uint idx = C->get_alias_index(TypeAryPtr::BYTES);
+  StrInflatedCopyNode* str = new StrInflatedCopyNode(control(), memory(idx), src, dst, count);
+  set_memory(_gvn.transform(str), idx);
+}
+
+void GraphKit::inflate_string_slow(Node* src, Node* dst, Node* start, Node* count) {
+  /**
+   * int i_char = start;
+   * for (int i_byte = 0; i_byte < count; i_byte++) {
+   *   dst[i_char++] = (char)(src[i_byte] & 0xff);
+   * }
+   */
+  add_predicate();
+  RegionNode* head = new RegionNode(3);
+  head->init_req(1, control());
+  gvn().set_type(head, Type::CONTROL);
+  record_for_igvn(head);
+
+  Node* i_byte = new PhiNode(head, TypeInt::INT);
+  i_byte->init_req(1, intcon(0));
+  gvn().set_type(i_byte, TypeInt::INT);
+  record_for_igvn(i_byte);
+
+  Node* i_char = new PhiNode(head, TypeInt::INT);
+  i_char->init_req(1, start);
+  gvn().set_type(i_char, TypeInt::INT);
+  record_for_igvn(i_char);
+
+  Node* mem = PhiNode::make(head, memory(TypeAryPtr::BYTES), Type::MEMORY, TypeAryPtr::BYTES);
+  gvn().set_type(mem, Type::MEMORY);
+  record_for_igvn(mem);
+  set_control(head);
+  set_memory(mem, TypeAryPtr::BYTES);
+  Node* ch = load_array_element(control(), src, i_byte, TypeAryPtr::BYTES);
+  Node* st = store_to_memory(control(), array_element_address(dst, i_char, T_BYTE),
+                             AndI(ch, intcon(0xff)), T_CHAR, TypeAryPtr::BYTES, MemNode::unordered);
+
+  IfNode* iff = create_and_map_if(head, Bool(CmpI(i_byte, count), BoolTest::lt), PROB_FAIR, COUNT_UNKNOWN);
+  head->init_req(2, IfTrue(iff));
+  mem->init_req(2, st);
+  i_byte->init_req(2, AddI(i_byte, intcon(1)));
+  i_char->init_req(2, AddI(i_char, intcon(2)));
+
+  set_control(IfFalse(iff));
+  set_memory(st, TypeAryPtr::BYTES);
 }
 
 Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) {
--- a/hotspot/src/share/vm/opto/graphKit.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -864,12 +864,14 @@
                   bool deoptimize_on_exception = false);
 
   // java.lang.String helpers
-  Node* load_String_offset(Node* ctrl, Node* str);
   Node* load_String_length(Node* ctrl, Node* str);
   Node* load_String_value(Node* ctrl, Node* str);
-  void store_String_offset(Node* ctrl, Node* str, Node* value);
-  void store_String_length(Node* ctrl, Node* str, Node* value);
+  Node* load_String_coder(Node* ctrl, Node* str);
   void store_String_value(Node* ctrl, Node* str, Node* value);
+  void store_String_coder(Node* ctrl, Node* str, Node* value);
+  Node* compress_string(Node* src, Node* dst, Node* count);
+  void inflate_string(Node* src, Node* dst, Node* count);
+  void inflate_string_slow(Node* src, Node* dst, Node* start, Node* count);
 
   // Handy for making control flow
   IfNode* create_and_map_if(Node* ctrl, Node* tst, float prob, float cnt) {
--- a/hotspot/src/share/vm/opto/idealKit.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/idealKit.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -530,7 +530,6 @@
          "call node must be constructed correctly");
 }
 
-
 void IdealKit::make_leaf_call_no_fp(const TypeFunc *slow_call_type,
                               address slow_call,
                               const char *leaf_name,
--- a/hotspot/src/share/vm/opto/idealKit.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/idealKit.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -183,6 +183,7 @@
   Node* AddI(Node* l, Node* r) { return transform(new AddINode(l, r)); }
   Node* SubI(Node* l, Node* r) { return transform(new SubINode(l, r)); }
   Node* AndI(Node* l, Node* r) { return transform(new AndINode(l, r)); }
+  Node* OrI(Node* l, Node* r)  { return transform(new OrINode(l, r));  }
   Node* MaxI(Node* l, Node* r) { return transform(new MaxINode(l, r)); }
   Node* LShiftI(Node* l, Node* r) { return transform(new LShiftINode(l, r)); }
   Node* CmpI(Node* l, Node* r) { return transform(new CmpINode(l, r)); }
@@ -256,7 +257,6 @@
                             Node* parm1,
                             Node* parm2,
                             Node* parm3);
-
 };
 
 #endif // SHARE_VM_OPTO_IDEALKIT_HPP
--- a/hotspot/src/share/vm/opto/intrinsicnode.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/intrinsicnode.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
 //------------------------------Ideal------------------------------------------
 // Return a node which is more "ideal" than the current node.  Strip out
 // control copies
-Node *StrIntrinsicNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+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;
@@ -55,11 +55,29 @@
 }
 
 //------------------------------Value------------------------------------------
-const Type *StrIntrinsicNode::Value( PhaseTransform *phase ) const {
+const Type* StrIntrinsicNode::Value(PhaseTransform* phase) const {
   if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
   return bottom_type();
 }
 
+uint StrIntrinsicNode::size_of() const { return sizeof(*this); }
+
+//=============================================================================
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node* StrCompressedCopyNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  return remove_dead_region(phase, can_reshape) ? this : NULL;
+}
+
+//=============================================================================
+//------------------------------Ideal------------------------------------------
+// Return a node which is more "ideal" than the current node.  Strip out
+// control copies
+Node* StrInflatedCopyNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+  return remove_dead_region(phase, can_reshape) ? this : NULL;
+}
+
 //=============================================================================
 //------------------------------match_edge-------------------------------------
 // Do not match memory edge
@@ -70,12 +88,12 @@
 //------------------------------Ideal------------------------------------------
 // Return a node which is more "ideal" than the current node.  Strip out
 // control copies
-Node *EncodeISOArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+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 {
+const Type* EncodeISOArrayNode::Value(PhaseTransform* phase) const {
   if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP;
   return bottom_type();
 }
--- a/hotspot/src/share/vm/opto/intrinsicnode.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/intrinsicnode.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,75 +35,131 @@
 // 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:
+ 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 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.
+// Base class for Ideal nodes used in String intrinsic code.
 class StrIntrinsicNode: public Node {
-  public:
+ public:
+  // Possible encodings of the two parameters passed to the string intrinsic.
+  // 'L' stands for Latin1 and 'U' stands for UTF16. For example, 'LU' means that
+  // the first string is Latin1 encoded and the second string is UTF16 encoded.
+  typedef enum ArgEncoding { LL, LU, UL, UU, none } ArgEnc;
+
+ protected:
+  // Encoding of strings. Used to select the right version of the intrinsic.
+  const ArgEncoding _encoding;
+  virtual uint size_of() const;
+
+ 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) {
+                   Node* s1, Node* c1, Node* s2, Node* c2, ArgEncoding encoding):
+  Node(control, char_array_mem, s1, c1, s2, c2), _encoding(encoding) {
   }
 
   StrIntrinsicNode(Node* control, Node* char_array_mem,
-                   Node* s1, Node* s2, Node* c):
-  Node(control, char_array_mem, s1, s2, c) {
+                   Node* s1, Node* s2, Node* c, ArgEncoding encoding):
+  Node(control, char_array_mem, s1, s2, c), _encoding(encoding) {
   }
 
   StrIntrinsicNode(Node* control, Node* char_array_mem,
-                   Node* s1, Node* s2):
-  Node(control, char_array_mem, s1, s2) {
+                   Node* s1, Node* s2, ArgEncoding encoding):
+  Node(control, char_array_mem, s1, s2), _encoding(encoding) {
   }
 
   virtual bool depends_only_on_test() const { return false; }
-  virtual const TypePtr* adr_type() const { return TypeAryPtr::CHARS; }
+  virtual const TypePtr* adr_type() const { return TypeAryPtr::BYTES; }
   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;
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+  virtual const Type* Value(PhaseTransform* phase) const;
+  ArgEncoding encoding() const { return _encoding; }
 };
 
 //------------------------------StrComp-------------------------------------
 class StrCompNode: public StrIntrinsicNode {
-  public:
+ 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) {};
+              Node* s1, Node* c1, Node* s2, Node* c2, ArgEncoding encoding):
+  StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2, encoding) {};
   virtual int Opcode() const;
   virtual const Type* bottom_type() const { return TypeInt::INT; }
 };
 
 //------------------------------StrEquals-------------------------------------
 class StrEqualsNode: public StrIntrinsicNode {
-  public:
+ public:
   StrEqualsNode(Node* control, Node* char_array_mem,
-                Node* s1, Node* s2, Node* c):
-  StrIntrinsicNode(control, char_array_mem, s1, s2, c) {};
+                Node* s1, Node* s2, Node* c, ArgEncoding encoding):
+  StrIntrinsicNode(control, char_array_mem, s1, s2, c, encoding) {};
   virtual int Opcode() const;
   virtual const Type* bottom_type() const { return TypeInt::BOOL; }
 };
 
 //------------------------------StrIndexOf-------------------------------------
 class StrIndexOfNode: public StrIntrinsicNode {
-  public:
+ 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) {};
+                 Node* s1, Node* c1, Node* s2, Node* c2, ArgEncoding encoding):
+  StrIntrinsicNode(control, char_array_mem, s1, c1, s2, c2, encoding) {};
+  virtual int Opcode() const;
+  virtual const Type* bottom_type() const { return TypeInt::INT; }
+};
+
+//------------------------------StrIndexOfChar-------------------------------------
+class StrIndexOfCharNode: public StrIntrinsicNode {
+ public:
+  StrIndexOfCharNode(Node* control, Node* char_array_mem,
+                     Node* s1, Node* c1, Node* c, ArgEncoding encoding):
+  StrIntrinsicNode(control, char_array_mem, s1, c1, c, encoding) {};
   virtual int Opcode() const;
   virtual const Type* bottom_type() const { return TypeInt::INT; }
 };
 
+//--------------------------StrCompressedCopy-------------------------------
+class StrCompressedCopyNode: public StrIntrinsicNode {
+ public:
+  StrCompressedCopyNode(Node* control, Node* arymem,
+                        Node* s1, Node* s2, Node* c):
+  StrIntrinsicNode(control, arymem, s1, s2, c, none) {};
+  virtual int Opcode() const;
+  virtual const Type* bottom_type() const { return TypeInt::INT; }
+  virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; }
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+//--------------------------StrInflatedCopy---------------------------------
+class StrInflatedCopyNode: public StrIntrinsicNode {
+ public:
+  StrInflatedCopyNode(Node* control, Node* arymem,
+                      Node* s1, Node* s2, Node* c):
+  StrIntrinsicNode(control, arymem, s1, s2, c, none) {};
+  virtual int Opcode() const;
+  virtual const Type* bottom_type() const { return Type::MEMORY; }
+  virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; }
+  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
 //------------------------------AryEq---------------------------------------
 class AryEqNode: public StrIntrinsicNode {
-  public:
-  AryEqNode(Node* control, Node* char_array_mem, Node* s1, Node* s2):
-  StrIntrinsicNode(control, char_array_mem, s1, s2) {};
+ public:
+  AryEqNode(Node* control, Node* char_array_mem,
+            Node* s1, Node* s2, ArgEncoding encoding):
+  StrIntrinsicNode(control, char_array_mem, s1, s2, encoding) {};
+  virtual int Opcode() const;
+  virtual const Type* bottom_type() const { return TypeInt::BOOL; }
+};
+
+//------------------------------HasNegatives---------------------------------
+class HasNegativesNode: public StrIntrinsicNode {
+ public:
+  HasNegativesNode(Node* control, Node* char_array_mem, Node* s1, Node* c1):
+  StrIntrinsicNode(control, char_array_mem, s1, c1, none) {};
   virtual int Opcode() const;
   virtual const Type* bottom_type() const { return TypeInt::BOOL; }
 };
@@ -112,16 +168,16 @@
 //------------------------------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) {};
+ 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;
+  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/lcm.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/lcm.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -196,8 +196,12 @@
     case Op_StrComp:
     case Op_StrEquals:
     case Op_StrIndexOf:
+    case Op_StrIndexOfChar:
     case Op_AryEq:
+    case Op_StrInflatedCopy:
+    case Op_StrCompressedCopy:
     case Op_EncodeISOArray:
+    case Op_HasNegatives:
       // Not a legit memory op for implicit null check regardless of
       // embedded loads
       continue;
@@ -806,7 +810,7 @@
   block->insert_node(proj, node_cnt++);
 
   // Select the right register save policy.
-  const char * save_policy;
+  const char *save_policy = NULL;
   switch (op) {
     case Op_CallRuntime:
     case Op_CallLeaf:
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -200,12 +200,16 @@
   }
   Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls);
 
-  Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2);
-  Node* make_string_method_node(int opcode, Node* str1, Node* str2);
-  bool inline_string_compareTo();
-  bool inline_string_indexOf();
-  Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
-  bool inline_string_equals();
+  Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae);
+  bool inline_string_compareTo(StrIntrinsicNode::ArgEnc ae);
+  bool inline_string_indexOf(StrIntrinsicNode::ArgEnc ae);
+  bool inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae);
+  bool inline_string_indexOfChar();
+  bool inline_string_equals(StrIntrinsicNode::ArgEnc ae);
+  bool inline_string_toBytesU();
+  bool inline_string_getCharsU();
+  bool inline_string_copy(bool compress);
+  bool inline_string_char_access(bool is_store);
   Node* round_double_node(Node* n);
   bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
   bool inline_math_native(vmIntrinsics::ID id);
@@ -251,7 +255,7 @@
   bool inline_native_newArray();
   bool inline_native_getLength();
   bool inline_array_copyOf(bool is_copyOfRange);
-  bool inline_array_equals();
+  bool inline_array_equals(StrIntrinsicNode::ArgEnc ae);
   void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark);
   bool inline_native_clone(bool is_virtual);
   bool inline_native_Reflection_getCallerClass();
@@ -298,6 +302,7 @@
   bool inline_updateBytesAdler32();
   bool inline_updateByteBufferAdler32();
   bool inline_multiplyToLen();
+  bool inline_hasNegatives();
   bool inline_squareToLen();
   bool inline_mulAdd();
   bool inline_montgomeryMultiply();
@@ -458,6 +463,7 @@
 bool LibraryCallKit::try_to_inline(int predicate) {
   // Handle symbolic names for otherwise undistinguished boolean switches:
   const bool is_store       = true;
+  const bool is_compress    = true;
   const bool is_native_ptr  = true;
   const bool is_static      = true;
   const bool is_volatile    = true;
@@ -512,9 +518,31 @@
 
   case vmIntrinsics::_arraycopy:                return inline_arraycopy();
 
-  case vmIntrinsics::_compareTo:                return inline_string_compareTo();
-  case vmIntrinsics::_indexOf:                  return inline_string_indexOf();
-  case vmIntrinsics::_equals:                   return inline_string_equals();
+  case vmIntrinsics::_compareToL:               return inline_string_compareTo(StrIntrinsicNode::LL);
+  case vmIntrinsics::_compareToU:               return inline_string_compareTo(StrIntrinsicNode::UU);
+  case vmIntrinsics::_compareToLU:              return inline_string_compareTo(StrIntrinsicNode::LU);
+  case vmIntrinsics::_compareToUL:              return inline_string_compareTo(StrIntrinsicNode::UL);
+
+  case vmIntrinsics::_indexOfL:                 return inline_string_indexOf(StrIntrinsicNode::LL);
+  case vmIntrinsics::_indexOfU:                 return inline_string_indexOf(StrIntrinsicNode::UU);
+  case vmIntrinsics::_indexOfUL:                return inline_string_indexOf(StrIntrinsicNode::UL);
+  case vmIntrinsics::_indexOfIL:                return inline_string_indexOfI(StrIntrinsicNode::LL);
+  case vmIntrinsics::_indexOfIU:                return inline_string_indexOfI(StrIntrinsicNode::UU);
+  case vmIntrinsics::_indexOfIUL:               return inline_string_indexOfI(StrIntrinsicNode::UL);
+  case vmIntrinsics::_indexOfU_char:            return inline_string_indexOfChar();
+
+  case vmIntrinsics::_equalsL:                  return inline_string_equals(StrIntrinsicNode::LL);
+  case vmIntrinsics::_equalsU:                  return inline_string_equals(StrIntrinsicNode::UU);
+
+  case vmIntrinsics::_toBytesStringU:           return inline_string_toBytesU();
+  case vmIntrinsics::_getCharsStringU:          return inline_string_getCharsU();
+  case vmIntrinsics::_getCharStringU:           return inline_string_char_access(!is_store);
+  case vmIntrinsics::_putCharStringU:           return inline_string_char_access( is_store);
+
+  case vmIntrinsics::_compressStringC:
+  case vmIntrinsics::_compressStringB:          return inline_string_copy( is_compress);
+  case vmIntrinsics::_inflateStringC:
+  case vmIntrinsics::_inflateStringB:           return inline_string_copy(!is_compress);
 
   case vmIntrinsics::_getObject:                return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT,  !is_volatile);
   case vmIntrinsics::_getBoolean:               return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile);
@@ -617,7 +645,8 @@
   case vmIntrinsics::_getLength:                return inline_native_getLength();
   case vmIntrinsics::_copyOf:                   return inline_array_copyOf(false);
   case vmIntrinsics::_copyOfRange:              return inline_array_copyOf(true);
-  case vmIntrinsics::_equalsC:                  return inline_array_equals();
+  case vmIntrinsics::_equalsB:                  return inline_array_equals(StrIntrinsicNode::LL);
+  case vmIntrinsics::_equalsC:                  return inline_array_equals(StrIntrinsicNode::UU);
   case vmIntrinsics::_clone:                    return inline_native_clone(intrinsic()->is_virtual());
 
   case vmIntrinsics::_isAssignableFrom:         return inline_native_subtype_check();
@@ -687,6 +716,7 @@
     return inline_ghash_processBlocks();
 
   case vmIntrinsics::_encodeISOArray:
+  case vmIntrinsics::_encodeByteISOArray:
     return inline_encodeISOArray();
 
   case vmIntrinsics::_updateCRC32:
@@ -711,6 +741,9 @@
   case vmIntrinsics::_isCompileConstant:
     return inline_isCompileConstant();
 
+  case vmIntrinsics::_hasNegatives:
+    return inline_hasNegatives();
+
   default:
     // If you get here, it may be that someone has added a new intrinsic
     // to the list in vmSymbols.hpp without implementing it here.
@@ -876,75 +909,24 @@
 
 
 //------------------------------make_string_method_node------------------------
-// Helper method for String intrinsic functions. This version is called
-// with str1 and str2 pointing to String object nodes.
-//
-Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2) {
-  Node* no_ctrl = NULL;
-
-  // Get start addr of string
-  Node* str1_value   = load_String_value(no_ctrl, str1);
-  Node* str1_offset  = load_String_offset(no_ctrl, str1);
-  Node* str1_start   = array_element_address(str1_value, str1_offset, T_CHAR);
-
-  // Get length of string 1
-  Node* str1_len  = load_String_length(no_ctrl, str1);
-
-  Node* str2_value   = load_String_value(no_ctrl, str2);
-  Node* str2_offset  = load_String_offset(no_ctrl, str2);
-  Node* str2_start   = array_element_address(str2_value, str2_offset, T_CHAR);
-
-  Node* str2_len = NULL;
-  Node* result = NULL;
-
-  switch (opcode) {
-  case Op_StrIndexOf:
-    // Get length of string 2
-    str2_len = load_String_length(no_ctrl, str2);
-
-    result = new StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
-                                str1_start, str1_len, str2_start, str2_len);
-    break;
-  case Op_StrComp:
-    // Get length of string 2
-    str2_len = load_String_length(no_ctrl, str2);
-
-    result = new StrCompNode(control(), memory(TypeAryPtr::CHARS),
-                             str1_start, str1_len, str2_start, str2_len);
-    break;
-  case Op_StrEquals:
-    result = new StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
-                               str1_start, str2_start, str1_len);
-    break;
-  default:
-    ShouldNotReachHere();
-    return NULL;
-  }
-
-  // All these intrinsics have checks.
-  C->set_has_split_ifs(true); // Has chance for split-if optimization
-
-  return _gvn.transform(result);
-}
-
-// Helper method for String intrinsic functions. This version is called
-// with str1 and str2 pointing to char[] nodes, with cnt1 and cnt2 pointing
-// to Int nodes containing the lenghts of str1 and str2.
-//
-Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) {
+// Helper method for String intrinsic functions. This version is called with
+// str1 and str2 pointing to byte[] nodes containing Latin1 or UTF16 encoded
+// characters (depending on 'is_byte'). cnt1 and cnt2 are pointing to Int nodes
+// containing the lengths of str1 and str2.
+Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae) {
   Node* result = NULL;
   switch (opcode) {
   case Op_StrIndexOf:
-    result = new StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
-                                str1_start, cnt1, str2_start, cnt2);
+    result = new StrIndexOfNode(control(), memory(TypeAryPtr::BYTES),
+                                str1_start, cnt1, str2_start, cnt2, ae);
     break;
   case Op_StrComp:
-    result = new StrCompNode(control(), memory(TypeAryPtr::CHARS),
-                             str1_start, cnt1, str2_start, cnt2);
+    result = new StrCompNode(control(), memory(TypeAryPtr::BYTES),
+                             str1_start, cnt1, str2_start, cnt2, ae);
     break;
   case Op_StrEquals:
-    result = new StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
-                               str1_start, str2_start, cnt1);
+    result = new StrEqualsNode(control(), memory(TypeAryPtr::BYTES),
+                               str1_start, str2_start, cnt1, ae);
     break;
   default:
     ShouldNotReachHere();
@@ -958,98 +940,54 @@
 }
 
 //------------------------------inline_string_compareTo------------------------
-// public int java.lang.String.compareTo(String anotherString);
-bool LibraryCallKit::inline_string_compareTo() {
-  Node* receiver = null_check(argument(0));
-  Node* arg      = null_check(argument(1));
-  if (stopped()) {
-    return true;
-  }
-  set_result(make_string_method_node(Op_StrComp, receiver, arg));
+bool LibraryCallKit::inline_string_compareTo(StrIntrinsicNode::ArgEnc ae) {
+  Node* arg1 = argument(0);
+  Node* arg2 = argument(1);
+
+  // Get start addr and length of first argument
+  Node* arg1_start  = array_element_address(arg1, intcon(0), T_BYTE);
+  Node* arg1_cnt    = load_array_length(arg1);
+
+  // Get start addr and length of second argument
+  Node* arg2_start  = array_element_address(arg2, intcon(0), T_BYTE);
+  Node* arg2_cnt    = load_array_length(arg2);
+
+  Node* result = make_string_method_node(Op_StrComp, arg1_start, arg1_cnt, arg2_start, arg2_cnt, ae);
+  set_result(result);
   return true;
 }
 
 //------------------------------inline_string_equals------------------------
-bool LibraryCallKit::inline_string_equals() {
-  Node* receiver = null_check_receiver();
-  // NOTE: Do not null check argument for String.equals() because spec
-  // allows to specify NULL as argument.
-  Node* argument = this->argument(1);
-  if (stopped()) {
-    return true;
-  }
+bool LibraryCallKit::inline_string_equals(StrIntrinsicNode::ArgEnc ae) {
+  Node* arg1 = argument(0);
+  Node* arg2 = argument(1);
 
   // paths (plus control) merge
-  RegionNode* region = new RegionNode(5);
+  RegionNode* region = new RegionNode(3);
   Node* phi = new PhiNode(region, TypeInt::BOOL);
 
-  // does source == target string?
-  Node* cmp = _gvn.transform(new CmpPNode(receiver, argument));
-  Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
-
-  Node* if_eq = generate_slow_guard(bol, NULL);
-  if (if_eq != NULL) {
-    // receiver == argument
-    phi->init_req(2, intcon(1));
-    region->init_req(2, if_eq);
-  }
-
-  // get String klass for instanceOf
-  ciInstanceKlass* klass = env()->String_klass();
-
   if (!stopped()) {
-    Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass)));
-    Node* cmp  = _gvn.transform(new CmpINode(inst, intcon(1)));
-    Node* bol  = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
-
-    Node* inst_false = generate_guard(bol, NULL, PROB_MIN);
-    //instanceOf == true, fallthrough
-
-    if (inst_false != NULL) {
-      phi->init_req(3, intcon(0));
-      region->init_req(3, inst_false);
-    }
-  }
-
-  if (!stopped()) {
-    const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
-
-    // Properly cast the argument to String
-    argument = _gvn.transform(new CheckCastPPNode(control(), argument, string_type));
-    // This path is taken only when argument's type is String:NotNull.
-    argument = cast_not_null(argument, false);
-
-    Node* no_ctrl = NULL;
-
-    // Get start addr of receiver
-    Node* receiver_val    = load_String_value(no_ctrl, receiver);
-    Node* receiver_offset = load_String_offset(no_ctrl, receiver);
-    Node* receiver_start = array_element_address(receiver_val, receiver_offset, T_CHAR);
-
-    // Get length of receiver
-    Node* receiver_cnt  = load_String_length(no_ctrl, receiver);
-
-    // Get start addr of argument
-    Node* argument_val    = load_String_value(no_ctrl, argument);
-    Node* argument_offset = load_String_offset(no_ctrl, argument);
-    Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR);
-
-    // Get length of argument
-    Node* argument_cnt  = load_String_length(no_ctrl, argument);
-
-    // Check for receiver count != argument count
-    Node* cmp = _gvn.transform(new CmpINode(receiver_cnt, argument_cnt));
+    // Get start addr and length of first argument
+    Node* arg1_start  = array_element_address(arg1, intcon(0), T_BYTE);
+    Node* arg1_cnt    = load_array_length(arg1);
+
+    // Get start addr and length of second argument
+    Node* arg2_start  = array_element_address(arg2, intcon(0), T_BYTE);
+    Node* arg2_cnt    = load_array_length(arg2);
+
+    // Check for arg1_cnt != arg2_cnt
+    Node* cmp = _gvn.transform(new CmpINode(arg1_cnt, arg2_cnt));
     Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
     Node* if_ne = generate_slow_guard(bol, NULL);
     if (if_ne != NULL) {
-      phi->init_req(4, intcon(0));
-      region->init_req(4, if_ne);
+      phi->init_req(2, intcon(0));
+      region->init_req(2, if_ne);
     }
 
     // Check for count == 0 is done by assembler code for StrEquals.
 
     if (!stopped()) {
-      Node* equals = make_string_method_node(Op_StrEquals, receiver_start, receiver_cnt, argument_start, argument_cnt);
+      Node* equals = make_string_method_node(Op_StrEquals, arg1_start, arg1_cnt, arg2_start, arg2_cnt, ae);
       phi->init_req(1, equals);
       region->init_req(1, control());
     }
@@ -1064,289 +1002,462 @@
 }
 
 //------------------------------inline_array_equals----------------------------
-bool LibraryCallKit::inline_array_equals() {
+bool LibraryCallKit::inline_array_equals(StrIntrinsicNode::ArgEnc ae) {
+  assert(ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::LL, "unsupported array types");
   Node* arg1 = argument(0);
   Node* arg2 = argument(1);
-  set_result(_gvn.transform(new AryEqNode(control(), memory(TypeAryPtr::CHARS), arg1, arg2)));
+
+  const TypeAryPtr* mtype = (ae == StrIntrinsicNode::UU) ? TypeAryPtr::CHARS : TypeAryPtr::BYTES;
+  set_result(_gvn.transform(new AryEqNode(control(), memory(mtype), arg1, arg2, ae)));
   return true;
 }
 
-// Java version of String.indexOf(constant string)
-// class StringDecl {
-//   StringDecl(char[] ca) {
-//     offset = 0;
-//     count = ca.length;
-//     value = ca;
-//   }
-//   int offset;
-//   int count;
-//   char[] value;
-// }
-//
-// static int string_indexOf_J(StringDecl string_object, char[] target_object,
-//                             int targetOffset, int cache_i, int md2) {
-//   int cache = cache_i;
-//   int sourceOffset = string_object.offset;
-//   int sourceCount = string_object.count;
-//   int targetCount = target_object.length;
-//
-//   int targetCountLess1 = targetCount - 1;
-//   int sourceEnd = sourceOffset + sourceCount - targetCountLess1;
-//
-//   char[] source = string_object.value;
-//   char[] target = target_object;
-//   int lastChar = target[targetCountLess1];
-//
-//  outer_loop:
-//   for (int i = sourceOffset; i < sourceEnd; ) {
-//     int src = source[i + targetCountLess1];
-//     if (src == lastChar) {
-//       // With random strings and a 4-character alphabet,
-//       // reverse matching at this point sets up 0.8% fewer
-//       // frames, but (paradoxically) makes 0.3% more probes.
-//       // Since those probes are nearer the lastChar probe,
-//       // there is may be a net D$ win with reverse matching.
-//       // But, reversing loop inhibits unroll of inner loop
-//       // for unknown reason.  So, does running outer loop from
-//       // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
-//       for (int j = 0; j < targetCountLess1; j++) {
-//         if (target[targetOffset + j] != source[i+j]) {
-//           if ((cache & (1 << source[i+j])) == 0) {
-//             if (md2 < j+1) {
-//               i += j+1;
-//               continue outer_loop;
-//             }
-//           }
-//           i += md2;
-//           continue outer_loop;
-//         }
-//       }
-//       return i - sourceOffset;
-//     }
-//     if ((cache & (1 << src)) == 0) {
-//       i += targetCountLess1;
-//     } // using "i += targetCount;" and an "else i++;" causes a jump to jump.
-//     i++;
-//   }
-//   return -1;
-// }
-
-//------------------------------string_indexOf------------------------
-Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_array, jint targetOffset_i,
-                                     jint cache_i, jint md2_i) {
-
-  Node* no_ctrl  = NULL;
-  float likely   = PROB_LIKELY(0.9);
-  float unlikely = PROB_UNLIKELY(0.9);
-
-  const int nargs = 0; // no arguments to push back for uncommon trap in predicate
-
-  Node* source        = load_String_value(no_ctrl, string_object);
-  Node* sourceOffset  = load_String_offset(no_ctrl, string_object);
-  Node* sourceCount   = load_String_length(no_ctrl, string_object);
-
-  Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)));
-  jint target_length = target_array->length();
-  const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin));
-  const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot);
-
-  // String.value field is known to be @Stable.
-  if (UseImplicitStableValues) {
-    target = cast_array_to_stable(target, target_type);
-  }
-
-  IdealKit kit(this, false, true);
-#define __ kit.
-  Node* zero             = __ ConI(0);
-  Node* one              = __ ConI(1);
-  Node* cache            = __ ConI(cache_i);
-  Node* md2              = __ ConI(md2_i);
-  Node* lastChar         = __ ConI(target_array->char_at(target_length - 1));
-  Node* targetCountLess1 = __ ConI(target_length - 1);
-  Node* targetOffset     = __ ConI(targetOffset_i);
-  Node* sourceEnd        = __ SubI(__ AddI(sourceOffset, sourceCount), targetCountLess1);
-
-  IdealVariable rtn(kit), i(kit), j(kit); __ declarations_done();
-  Node* outer_loop = __ make_label(2 /* goto */);
-  Node* return_    = __ make_label(1);
-
-  __ set(rtn,__ ConI(-1));
-  __ loop(this, nargs, i, sourceOffset, BoolTest::lt, sourceEnd); {
-       Node* i2  = __ AddI(__ value(i), targetCountLess1);
-       // pin to prohibit loading of "next iteration" value which may SEGV (rare)
-       Node* src = load_array_element(__ ctrl(), source, i2, TypeAryPtr::CHARS);
-       __ if_then(src, BoolTest::eq, lastChar, unlikely); {
-         __ loop(this, nargs, j, zero, BoolTest::lt, targetCountLess1); {
-              Node* tpj = __ AddI(targetOffset, __ value(j));
-              Node* targ = load_array_element(no_ctrl, target, tpj, target_type);
-              Node* ipj  = __ AddI(__ value(i), __ value(j));
-              Node* src2 = load_array_element(no_ctrl, source, ipj, TypeAryPtr::CHARS);
-              __ if_then(targ, BoolTest::ne, src2); {
-                __ if_then(__ AndI(cache, __ LShiftI(one, src2)), BoolTest::eq, zero); {
-                  __ if_then(md2, BoolTest::lt, __ AddI(__ value(j), one)); {
-                    __ increment(i, __ AddI(__ value(j), one));
-                    __ goto_(outer_loop);
-                  } __ end_if(); __ dead(j);
-                }__ end_if(); __ dead(j);
-                __ increment(i, md2);
-                __ goto_(outer_loop);
-              }__ end_if();
-              __ increment(j, one);
-         }__ end_loop(); __ dead(j);
-         __ set(rtn, __ SubI(__ value(i), sourceOffset)); __ dead(i);
-         __ goto_(return_);
-       }__ end_if();
-       __ if_then(__ AndI(cache, __ LShiftI(one, src)), BoolTest::eq, zero, likely); {
-         __ increment(i, targetCountLess1);
-       }__ end_if();
-       __ increment(i, one);
-       __ bind(outer_loop);
-  }__ end_loop(); __ dead(i);
-  __ bind(return_);
-
-  // Final sync IdealKit and GraphKit.
-  final_sync(kit);
-  Node* result = __ value(rtn);
-#undef __
-  C->set_has_loops(true);
-  return result;
+//------------------------------inline_hasNegatives------------------------------
+bool LibraryCallKit::inline_hasNegatives() {
+  if (too_many_traps(Deoptimization::Reason_intrinsic))  return false;
+
+  assert(callee()->signature()->size() == 3, "hasNegatives has 3 parameters");
+  // no receiver since it is static method
+  Node* ba         = argument(0);
+  Node* offset     = argument(1);
+  Node* len        = argument(2);
+
+  RegionNode* bailout = new RegionNode(1);
+  record_for_igvn(bailout);
+
+  // offset must not be negative.
+  generate_negative_guard(offset, bailout);
+
+  // offset + length must not exceed length of ba.
+  generate_limit_guard(offset, len, load_array_length(ba), bailout);
+
+  if (bailout->req() > 1) {
+    PreserveJVMState pjvms(this);
+    set_control(_gvn.transform(bailout));
+    uncommon_trap(Deoptimization::Reason_intrinsic,
+                  Deoptimization::Action_maybe_recompile);
+  }
+  if (!stopped()) {
+    Node* ba_start = array_element_address(ba, offset, T_BYTE);
+    Node* result = new HasNegativesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len);
+    set_result(_gvn.transform(result));
+  }
+  return true;
 }
 
 //------------------------------inline_string_indexOf------------------------
-bool LibraryCallKit::inline_string_indexOf() {
-  Node* receiver = argument(0);
-  Node* arg      = argument(1);
-
-  Node* result;
-  if (Matcher::has_match_rule(Op_StrIndexOf) &&
-      UseSSE42Intrinsics) {
-    // Generate SSE4.2 version of indexOf
-    // We currently only have match rules that use SSE4.2
-
-    receiver = null_check(receiver);
-    arg      = null_check(arg);
-    if (stopped()) {
-      return true;
-    }
-
-    // Make the merge point
-    RegionNode* result_rgn = new RegionNode(4);
-    Node*       result_phi = new PhiNode(result_rgn, TypeInt::INT);
-    Node* no_ctrl  = NULL;
-
-    // Get start addr of source string
-    Node* source = load_String_value(no_ctrl, receiver);
-    Node* source_offset = load_String_offset(no_ctrl, receiver);
-    Node* source_start = array_element_address(source, source_offset, T_CHAR);
-
-    // Get length of source string
-    Node* source_cnt  = load_String_length(no_ctrl, receiver);
-
-    // Get start addr of substring
-    Node* substr = load_String_value(no_ctrl, arg);
-    Node* substr_offset = load_String_offset(no_ctrl, arg);
-    Node* substr_start = array_element_address(substr, substr_offset, T_CHAR);
-
-    // Get length of source string
-    Node* substr_cnt  = load_String_length(no_ctrl, arg);
-
-    // Check for substr count > string count
-    Node* cmp = _gvn.transform(new CmpINode(substr_cnt, source_cnt));
-    Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::gt));
-    Node* if_gt = generate_slow_guard(bol, NULL);
-    if (if_gt != NULL) {
-      result_phi->init_req(2, intcon(-1));
-      result_rgn->init_req(2, if_gt);
-    }
-
-    if (!stopped()) {
-      // Check for substr count == 0
-      cmp = _gvn.transform(new CmpINode(substr_cnt, intcon(0)));
-      bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
-      Node* if_zero = generate_slow_guard(bol, NULL);
-      if (if_zero != NULL) {
-        result_phi->init_req(3, intcon(0));
-        result_rgn->init_req(3, if_zero);
-      }
-    }
-
-    if (!stopped()) {
-      result = make_string_method_node(Op_StrIndexOf, source_start, source_cnt, substr_start, substr_cnt);
-      result_phi->init_req(1, result);
-      result_rgn->init_req(1, control());
+bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) {
+  if (!Matcher::has_match_rule(Op_StrIndexOf) || !UseSSE42Intrinsics) {
+    return false;
+  }
+  Node* src = argument(0);
+  Node* tgt = argument(1);
+
+  // Make the merge point
+  RegionNode* result_rgn = new RegionNode(4);
+  Node*       result_phi = new PhiNode(result_rgn, TypeInt::INT);
+
+  // Get start addr and length of source string
+  Node* src_start = array_element_address(src, intcon(0), T_BYTE);
+  Node* src_count = load_array_length(src);
+
+  // Get start addr and length of substring
+  Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE);
+  Node* tgt_count = load_array_length(tgt);
+
+  if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) {
+    // Divide src size by 2 if String is UTF16 encoded
+    src_count = _gvn.transform(new RShiftINode(src_count, intcon(1)));
+  }
+  if (ae == StrIntrinsicNode::UU) {
+    // Divide substring size by 2 if String is UTF16 encoded
+    tgt_count = _gvn.transform(new RShiftINode(tgt_count, intcon(1)));
+  }
+
+  // Check for substr count > string count
+  Node* cmp = _gvn.transform(new CmpINode(tgt_count, src_count));
+  Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::gt));
+  Node* if_gt = generate_slow_guard(bol, NULL);
+  if (if_gt != NULL) {
+    result_phi->init_req(2, intcon(-1));
+    result_rgn->init_req(2, if_gt);
+  }
+
+  if (!stopped()) {
+    // Check for substr count == 0
+    cmp = _gvn.transform(new CmpINode(tgt_count, intcon(0)));
+    bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
+    Node* if_zero = generate_slow_guard(bol, NULL);
+    if (if_zero != NULL) {
+      result_phi->init_req(3, intcon(0));
+      result_rgn->init_req(3, if_zero);
     }
-    set_control(_gvn.transform(result_rgn));
-    record_for_igvn(result_rgn);
-    result = _gvn.transform(result_phi);
-
-  } else { // Use LibraryCallKit::string_indexOf
-    // don't intrinsify if argument isn't a constant string.
-    if (!arg->is_Con()) {
-     return false;
-    }
-    const TypeOopPtr* str_type = _gvn.type(arg)->isa_oopptr();
-    if (str_type == NULL) {
-      return false;
-    }
-    ciInstanceKlass* klass = env()->String_klass();
-    ciObject* str_const = str_type->const_oop();
-    if (str_const == NULL || str_const->klass() != klass) {
-      return false;
-    }
-    ciInstance* str = str_const->as_instance();
-    assert(str != NULL, "must be instance");
-
-    ciObject* v = str->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object();
-    ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array
-
-    int o;
-    int c;
-    if (java_lang_String::has_offset_field()) {
-      o = str->field_value_by_offset(java_lang_String::offset_offset_in_bytes()).as_int();
-      c = str->field_value_by_offset(java_lang_String::count_offset_in_bytes()).as_int();
-    } else {
-      o = 0;
-      c = pat->length();
+  }
+
+  if (!stopped()) {
+    Node* result = make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae);
+    result_phi->init_req(1, result);
+    result_rgn->init_req(1, control());
+  }
+  set_control(_gvn.transform(result_rgn));
+  record_for_igvn(result_rgn);
+  set_result(_gvn.transform(result_phi));
+
+  return true;
+}
+
+//-----------------------------inline_string_indexOf-----------------------
+bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) {
+  if (!Matcher::has_match_rule(Op_StrIndexOf) || !UseSSE42Intrinsics) {
+    return false;
+  }
+  assert(callee()->signature()->size() == 5, "String.indexOf() has 5 arguments");
+  Node* src         = argument(0); // byte[]
+  Node* src_count   = argument(1);
+  Node* tgt         = argument(2); // byte[]
+  Node* tgt_count   = argument(3);
+  Node* from_index  = argument(4);
+
+  // Java code which calls this method has range checks for from_index value.
+  src_count = _gvn.transform(new SubINode(src_count, from_index));
+
+  // Multiply byte array index by 2 if String is UTF16 encoded
+  Node* src_offset = (ae == StrIntrinsicNode::LL) ? from_index : _gvn.transform(new LShiftINode(from_index, intcon(1)));
+  Node* src_start = array_element_address(src, src_offset, T_BYTE);
+  Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE);
+
+  Node* result = make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae);
+
+  // The result is index relative to from_index if substring was found, -1 otherwise.
+  // Generate code which will fold into cmove.
+  RegionNode* region = new RegionNode(3);
+  Node* phi = new PhiNode(region, TypeInt::INT);
+
+  Node* cmp = _gvn.transform(new CmpINode(result, intcon(0)));
+  Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt));
+
+  Node* if_lt = generate_slow_guard(bol, NULL);
+  if (if_lt != NULL) {
+    // result == -1
+    phi->init_req(2, result);
+    region->init_req(2, if_lt);
+  }
+  if (!stopped()) {
+    result = _gvn.transform(new AddINode(result, from_index));
+    phi->init_req(1, result);
+    region->init_req(1, control());
+  }
+
+  set_control(_gvn.transform(region));
+  record_for_igvn(region);
+  set_result(_gvn.transform(phi));
+
+  return true;
+}
+
+//-----------------------------inline_string_indexOfChar-----------------------
+bool LibraryCallKit::inline_string_indexOfChar() {
+  if (!Matcher::has_match_rule(Op_StrIndexOfChar) || !(UseSSE > 4)) {
+    return false;
+  }
+  assert(callee()->signature()->size() == 4, "String.indexOfChar() has 4 arguments");
+  Node* src         = argument(0); // byte[]
+  Node* tgt         = argument(1); // tgt is int ch
+  Node* from_index  = argument(2);
+  Node* max         = argument(3);
+
+  Node* src_offset = _gvn.transform(new LShiftINode(from_index, intcon(1)));
+  Node* src_start = array_element_address(src, src_offset, T_BYTE);
+
+  Node* src_count = _gvn.transform(new SubINode(max, from_index));
+
+  RegionNode* region = new RegionNode(3);
+  Node* phi = new PhiNode(region, TypeInt::INT);
+
+  Node* result = new StrIndexOfCharNode(control(), memory(TypeAryPtr::BYTES), src_start, src_count, tgt, StrIntrinsicNode::none);
+  C->set_has_split_ifs(true); // Has chance for split-if optimization
+  _gvn.transform(result);
+
+  Node* cmp = _gvn.transform(new CmpINode(result, intcon(0)));
+  Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt));
+
+  Node* if_lt = generate_slow_guard(bol, NULL);
+  if (if_lt != NULL) {
+    // result == -1
+    phi->init_req(2, result);
+    region->init_req(2, if_lt);
+  }
+  if (!stopped()) {
+    result = _gvn.transform(new AddINode(result, from_index));
+    phi->init_req(1, result);
+    region->init_req(1, control());
+  }
+  set_control(_gvn.transform(region));
+  record_for_igvn(region);
+  set_result(_gvn.transform(phi));
+
+  return true;
+}
+//---------------------------inline_string_copy---------------------
+// compressIt == true --> generate a compressed copy operation (compress char[]/byte[] to byte[])
+//   int StringUTF16.compress(char[] src, int srcOff, byte[] dst, int dstOff, int len)
+//   int StringUTF16.compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len)
+// compressIt == false --> generate an inflated copy operation (inflate byte[] to char[]/byte[])
+//   void StringLatin1.inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len)
+//   void StringLatin1.inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len)
+bool LibraryCallKit::inline_string_copy(bool compress) {
+  int nargs = 5;  // 2 oops, 3 ints
+  assert(callee()->signature()->size() == nargs, "string copy has 5 arguments");
+
+  Node* src         = argument(0);
+  Node* src_offset  = argument(1);
+  Node* dst         = argument(2);
+  Node* dst_offset  = argument(3);
+  Node* length      = argument(4);
+
+  // Check for allocation before we add nodes that would confuse
+  // tightly_coupled_allocation()
+  AllocateArrayNode* alloc = tightly_coupled_allocation(dst, NULL);
+
+  // Figure out the size and type of the elements we will be copying.
+  const Type* src_type = src->Value(&_gvn);
+  const Type* dst_type = dst->Value(&_gvn);
+  BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  assert((compress && dst_elem == T_BYTE && (src_elem == T_BYTE || src_elem == T_CHAR)) ||
+         (!compress && src_elem == T_BYTE && (dst_elem == T_BYTE || dst_elem == T_CHAR)),
+         "Unsupported array types for inline_string_copy");
+
+  // Convert char[] offsets to byte[] offsets
+  if (compress && src_elem == T_BYTE) {
+    src_offset = _gvn.transform(new LShiftINode(src_offset, intcon(1)));
+  } else if (!compress && dst_elem == T_BYTE) {
+    dst_offset = _gvn.transform(new LShiftINode(dst_offset, intcon(1)));
+  }
+
+  Node* src_start = array_element_address(src, src_offset, src_elem);
+  Node* dst_start = array_element_address(dst, dst_offset, dst_elem);
+  // 'src_start' points to src array + scaled offset
+  // 'dst_start' points to dst array + scaled offset
+  Node* count = NULL;
+  if (compress) {
+    count = compress_string(src_start, dst_start, length);
+  } else {
+    inflate_string(src_start, dst_start, length);
+  }
+
+  if (alloc != NULL) {
+    if (alloc->maybe_set_complete(&_gvn)) {
+      // "You break it, you buy it."
+      InitializeNode* init = alloc->initialization();
+      assert(init->is_complete(), "we just did this");
+      init->set_complete_with_arraycopy();
+      assert(dst->is_CheckCastPP(), "sanity");
+      assert(dst->in(0)->in(0) == init, "dest pinned");
     }
-
-    // constant strings have no offset and count == length which
-    // simplifies the resulting code somewhat so lets optimize for that.
-    if (o != 0 || c != pat->length()) {
-     return false;
+    // Do not let stores that initialize this object be reordered with
+    // a subsequent store that would make this object accessible by
+    // other threads.
+    // Record what AllocateNode this StoreStore protects so that
+    // escape analysis can go from the MemBarStoreStoreNode to the
+    // AllocateNode and eliminate the MemBarStoreStoreNode if possible
+    // based on the escape status of the AllocateNode.
+    insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress));
+  }
+  if (compress) {
+    set_result(_gvn.transform(count));
+  }
+  return true;
+}
+
+#ifdef _LP64
+#define XTOP ,top() /*additional argument*/
+#else  //_LP64
+#define XTOP        /*no additional argument*/
+#endif //_LP64
+
+//------------------------inline_string_toBytesU--------------------------
+// public static byte[] StringUTF16.toBytes(char[] value, int off, int len)
+bool LibraryCallKit::inline_string_toBytesU() {
+  // Get the arguments.
+  Node* value     = argument(0);
+  Node* offset    = argument(1);
+  Node* length    = argument(2);
+
+  Node* newcopy = NULL;
+
+  // Set the original stack and the reexecute bit for the interpreter to reexecute
+  // the bytecode that invokes StringUTF16.toBytes() if deoptimization happens.
+  { PreserveReexecuteState preexecs(this);
+    jvms()->set_should_reexecute(true);
+
+    // Check if a null path was taken unconditionally.
+    value = null_check(value);
+
+    RegionNode* bailout = new RegionNode(1);
+    record_for_igvn(bailout);
+
+    // Make sure that resulting byte[] length does not overflow Integer.MAX_VALUE
+    generate_negative_guard(length, bailout);
+    generate_limit_guard(length, intcon(0), intcon(max_jint/2), bailout);
+
+    if (bailout->req() > 1) {
+      PreserveJVMState pjvms(this);
+      set_control(_gvn.transform(bailout));
+      uncommon_trap(Deoptimization::Reason_intrinsic,
+                    Deoptimization::Action_maybe_recompile);
     }
-
-    receiver = null_check(receiver, T_OBJECT);
-    // NOTE: No null check on the argument is needed since it's a constant String oop.
-    if (stopped()) {
-      return true;
-    }
-
-    // The null string as a pattern always returns 0 (match at beginning of string)
-    if (c == 0) {
-      set_result(intcon(0));
-      return true;
+    if (stopped()) return true;
+
+    // Range checks are done by caller.
+
+    Node* size = _gvn.transform(new LShiftINode(length, intcon(1)));
+    Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_BYTE)));
+    newcopy = new_array(klass_node, size, 0);  // no arguments to push
+    AllocateArrayNode* alloc = tightly_coupled_allocation(newcopy, NULL);
+
+    // Calculate starting addresses.
+    Node* src_start = array_element_address(value, offset, T_CHAR);
+    Node* dst_start = basic_plus_adr(newcopy, arrayOopDesc::base_offset_in_bytes(T_BYTE));
+
+    // Check if src array address is aligned to HeapWordSize (dst is always aligned)
+    const TypeInt* toffset = gvn().type(offset)->is_int();
+    bool aligned = toffset->is_con() && ((toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
+
+    // Figure out which arraycopy runtime method to call (disjoint, uninitialized).
+    const char* copyfunc_name = "arraycopy";
+    address     copyfunc_addr = StubRoutines::select_arraycopy_function(T_CHAR, aligned, true, copyfunc_name, true);
+    Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                      OptoRuntime::fast_arraycopy_Type(),
+                      copyfunc_addr, copyfunc_name, TypeRawPtr::BOTTOM,
+                      src_start, dst_start, ConvI2X(length) XTOP);
+    // Do not let reads from the cloned object float above the arraycopy.
+    if (alloc != NULL) {
+      if (alloc->maybe_set_complete(&_gvn)) {
+        // "You break it, you buy it."
+        InitializeNode* init = alloc->initialization();
+        assert(init->is_complete(), "we just did this");
+        init->set_complete_with_arraycopy();
+        assert(newcopy->is_CheckCastPP(), "sanity");
+        assert(newcopy->in(0)->in(0) == init, "dest pinned");
+      }
+      // Do not let stores that initialize this object be reordered with
+      // a subsequent store that would make this object accessible by
+      // other threads.
+      // Record what AllocateNode this StoreStore protects so that
+      // escape analysis can go from the MemBarStoreStoreNode to the
+      // AllocateNode and eliminate the MemBarStoreStoreNode if possible
+      // based on the escape status of the AllocateNode.
+      insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress));
+    } else {
+      insert_mem_bar(Op_MemBarCPUOrder);
     }
-
-    // Generate default indexOf
-    jchar lastChar = pat->char_at(o + (c - 1));
-    int cache = 0;
-    int i;
-    for (i = 0; i < c - 1; i++) {
-      assert(i < pat->length(), "out of range");
-      cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1)));
+  } // original reexecute is set back here
+
+  C->set_has_split_ifs(true); // Has chance for split-if optimization
+  if (!stopped()) {
+    set_result(newcopy);
+  }
+  return true;
+}
+
+//------------------------inline_string_getCharsU--------------------------
+// public void StringUTF16.getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin)
+bool LibraryCallKit::inline_string_getCharsU() {
+  if (too_many_traps(Deoptimization::Reason_intrinsic))  return false;
+
+  // Get the arguments.
+  Node* value     = argument(0);
+  Node* src_begin = argument(1);
+  Node* src_end   = argument(2); // exclusive offset (i < src_end)
+  Node* dst       = argument(3);
+  Node* dst_begin = argument(4);
+
+  // Check for allocation before we add nodes that would confuse
+  // tightly_coupled_allocation()
+  AllocateArrayNode* alloc = tightly_coupled_allocation(dst, NULL);
+
+  // Check if a null path was taken unconditionally.
+  value = null_check(value);
+  dst = null_check(dst);
+  if (stopped()) {
+    return true;
+  }
+
+  // Range checks are done by caller.
+
+  // Get length and convert char[] offset to byte[] offset
+  Node* length = _gvn.transform(new SubINode(src_end, src_begin));
+  src_begin = _gvn.transform(new LShiftINode(src_begin, intcon(1)));
+
+  if (!stopped()) {
+    // Calculate starting addresses.
+    Node* src_start = array_element_address(value, src_begin, T_BYTE);
+    Node* dst_start = array_element_address(dst, dst_begin, T_CHAR);
+
+    // Check if array addresses are aligned to HeapWordSize
+    const TypeInt* tsrc = gvn().type(src_begin)->is_int();
+    const TypeInt* tdst = gvn().type(dst_begin)->is_int();
+    bool aligned = tsrc->is_con() && ((tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) &&
+                   tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
+
+    // Figure out which arraycopy runtime method to call (disjoint, uninitialized).
+    const char* copyfunc_name = "arraycopy";
+    address     copyfunc_addr = StubRoutines::select_arraycopy_function(T_CHAR, aligned, true, copyfunc_name, true);
+    Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                      OptoRuntime::fast_arraycopy_Type(),
+                      copyfunc_addr, copyfunc_name, TypeRawPtr::BOTTOM,
+                      src_start, dst_start, ConvI2X(length) XTOP);
+    // Do not let reads from the cloned object float above the arraycopy.
+    if (alloc != NULL) {
+      if (alloc->maybe_set_complete(&_gvn)) {
+        // "You break it, you buy it."
+        InitializeNode* init = alloc->initialization();
+        assert(init->is_complete(), "we just did this");
+        init->set_complete_with_arraycopy();
+        assert(dst->is_CheckCastPP(), "sanity");
+        assert(dst->in(0)->in(0) == init, "dest pinned");
+      }
+      // Do not let stores that initialize this object be reordered with
+      // a subsequent store that would make this object accessible by
+      // other threads.
+      // Record what AllocateNode this StoreStore protects so that
+      // escape analysis can go from the MemBarStoreStoreNode to the
+      // AllocateNode and eliminate the MemBarStoreStoreNode if possible
+      // based on the escape status of the AllocateNode.
+      insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress));
+    } else {
+      insert_mem_bar(Op_MemBarCPUOrder);
     }
-
-    int md2 = c;
-    for (i = 0; i < c - 1; i++) {
-      assert(i < pat->length(), "out of range");
-      if (pat->char_at(o + i) == lastChar) {
-        md2 = (c - 1) - i;
-      }
-    }
-
-    result = string_indexOf(receiver, pat, o, cache, md2);
-  }
-  set_result(result);
+  }
+
+  C->set_has_split_ifs(true); // Has chance for split-if optimization
+  return true;
+}
+
+//----------------------inline_string_char_access----------------------------
+// Store/Load char to/from byte[] array.
+// static void StringUTF16.putChar(byte[] val, int index, int c)
+// static char StringUTF16.getChar(byte[] val, int index)
+bool LibraryCallKit::inline_string_char_access(bool is_store) {
+  Node* value  = argument(0);
+  Node* index  = argument(1);
+  Node* ch = is_store ? argument(2) : NULL;
+
+  // This intrinsic accesses byte[] array as char[] array. Computing the offsets
+  // correctly requires matched array shapes.
+  assert (arrayOopDesc::base_offset_in_bytes(T_CHAR) == arrayOopDesc::base_offset_in_bytes(T_BYTE),
+          "sanity: byte[] and char[] bases agree");
+  assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2,
+          "sanity: byte[] and char[] scales agree");
+
+  Node* adr = array_element_address(value, index, T_CHAR);
+  if (is_store) {
+    (void) store_to_memory(control(), adr, ch, T_CHAR, TypeAryPtr::BYTES, MemNode::unordered);
+  } else {
+    ch = make_load(control(), adr, TypeInt::CHAR, T_CHAR, MemNode::unordered);
+    set_result(ch);
+  }
   return true;
 }
 
@@ -1365,7 +1476,7 @@
 // public static double Math.log10(double)
 bool LibraryCallKit::inline_math(vmIntrinsics::ID id) {
   Node* arg = round_double_node(argument(0));
-  Node* n;
+  Node* n = NULL;
   switch (id) {
   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
@@ -2110,7 +2221,7 @@
 // inline long       Long.reverseBytes(long)
 bool LibraryCallKit::inline_number_methods(vmIntrinsics::ID id) {
   Node* arg = argument(0);
-  Node* n;
+  Node* n = NULL;
   switch (id) {
   case vmIntrinsics::_numberOfLeadingZeros_i:   n = new CountLeadingZerosINode( arg);  break;
   case vmIntrinsics::_numberOfLeadingZeros_l:   n = new CountLeadingZerosLNode( arg);  break;
@@ -2650,7 +2761,7 @@
 
   // For now, we handle only those cases that actually exist: ints,
   // longs, and Object. Adding others should be straightforward.
-  Node* load_store;
+  Node* load_store = NULL;
   switch(type) {
   case T_INT:
     if (kind == LS_xadd) {
@@ -2781,9 +2892,9 @@
 }
 
 //----------------------------inline_unsafe_ordered_store----------------------
-// public native void sun.misc.Unsafe.putOrderedObject(Object o, long offset, Object x);
-// public native void sun.misc.Unsafe.putOrderedInt(Object o, long offset, int x);
-// public native void sun.misc.Unsafe.putOrderedLong(Object o, long offset, long x);
+// public native void Unsafe.putOrderedObject(Object o, long offset, Object x);
+// public native void Unsafe.putOrderedInt(Object o, long offset, int x);
+// public native void Unsafe.putOrderedLong(Object o, long offset, long x);
 bool LibraryCallKit::inline_unsafe_ordered_store(BasicType type) {
   // This is another variant of inline_unsafe_access, differing in
   // that it always issues store-store ("release") barrier and ensures
@@ -2877,7 +2988,7 @@
 }
 
 //----------------------------inline_unsafe_allocate---------------------------
-// public native Object sun.misc.Unsafe.allocateInstance(Class<?> cls);
+// public native Object Unsafe.allocateInstance(Class<?> cls);
 bool LibraryCallKit::inline_unsafe_allocate() {
   if (callee()->is_static())  return false;  // caller must have the capability!
 
@@ -3656,7 +3767,7 @@
   Node* end               = is_copyOfRange? argument(2): argument(1);
   Node* array_type_mirror = is_copyOfRange? argument(3): argument(2);
 
-  Node* newcopy;
+  Node* newcopy = NULL;
 
   // Set the original stack and the reexecute bit for the interpreter to reexecute
   // the bytecode that invokes Arrays.copyOf if deoptimization happens.
@@ -4091,7 +4202,7 @@
 
 bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) {
   Node* arg = argument(0);
-  Node* result;
+  Node* result = NULL;
 
   switch (id) {
   case vmIntrinsics::_floatToRawIntBits:    result = new MoveF2INode(arg);  break;
@@ -4189,14 +4300,8 @@
   return true;
 }
 
-#ifdef _LP64
-#define XTOP ,top() /*additional argument*/
-#else  //_LP64
-#define XTOP        /*no additional argument*/
-#endif //_LP64
-
 //----------------------inline_unsafe_copyMemory-------------------------
-// public native void sun.misc.Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
+// public native void Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
 bool LibraryCallKit::inline_unsafe_copyMemory() {
   if (callee()->is_static())  return false;  // caller must have the capability!
   null_check_receiver();  // null-check receiver
@@ -5003,10 +5108,11 @@
   // Figure out the size and type of the elements we will be copying.
   BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
   BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
-  if (src_elem != T_CHAR || dst_elem != T_BYTE) {
+  if (!((src_elem == T_CHAR) || (src_elem== T_BYTE)) || dst_elem != T_BYTE) {
     return false;
   }
-  Node* src_start = array_element_address(src, src_offset, src_elem);
+
+  Node* src_start = array_element_address(src, src_offset, T_CHAR);
   Node* dst_start = array_element_address(dst, dst_offset, dst_elem);
   // 'src_start' points to src array + scaled offset
   // 'dst_start' points to dst array + scaled offset
@@ -5124,7 +5230,7 @@
 
 //-------------inline_squareToLen------------------------------------
 bool LibraryCallKit::inline_squareToLen() {
-  assert(UseSquareToLenIntrinsic, "not implementated on this platform");
+  assert(UseSquareToLenIntrinsic, "not implemented on this platform");
 
   address stubAddr = StubRoutines::squareToLen();
   if (stubAddr == NULL) {
@@ -5170,7 +5276,7 @@
 
 //-------------inline_mulAdd------------------------------------------
 bool LibraryCallKit::inline_mulAdd() {
-  assert(UseMulAddIntrinsic, "not implementated on this platform");
+  assert(UseMulAddIntrinsic, "not implemented on this platform");
 
   address stubAddr = StubRoutines::mulAdd();
   if (stubAddr == NULL) {
@@ -5720,7 +5826,7 @@
 
 //------------------------------inline_aescrypt_Block-----------------------
 bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) {
-  address stubAddr;
+  address stubAddr = NULL;
   const char *stubName;
   assert(UseAES, "need AES instruction support");
 
@@ -5786,8 +5892,8 @@
 
 //------------------------------inline_cipherBlockChaining_AESCrypt-----------------------
 bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
-  address stubAddr;
-  const char *stubName;
+  address stubAddr = NULL;
+  const char *stubName = NULL;
 
   assert(UseAES, "need AES instruction support");
 
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -622,8 +622,10 @@
       case Op_StrComp:
       case Op_StrEquals:
       case Op_StrIndexOf:
+      case Op_StrIndexOfChar:
       case Op_EncodeISOArray:
-      case Op_AryEq: {
+      case Op_AryEq:
+      case Op_HasNegatives: {
         return false;
       }
 #if INCLUDE_RTM_OPT
@@ -741,8 +743,10 @@
       case Op_StrComp:
       case Op_StrEquals:
       case Op_StrIndexOf:
+      case Op_StrIndexOfChar:
       case Op_EncodeISOArray:
-      case Op_AryEq: {
+      case Op_AryEq:
+      case Op_HasNegatives: {
         // Do not unroll a loop with String intrinsics code.
         // String intrinsics are large and have loops.
         return false;
--- a/hotspot/src/share/vm/opto/loopnode.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -3494,7 +3494,9 @@
     case Op_StrComp:            // Does a bunch of load-like effects
     case Op_StrEquals:
     case Op_StrIndexOf:
+    case Op_StrIndexOfChar:
     case Op_AryEq:
+    case Op_HasNegatives:
       pinned = false;
     }
     if( pinned ) {
--- a/hotspot/src/share/vm/opto/macro.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/macro.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -379,13 +379,25 @@
       if (mem->is_LoadStore()) {
         adr = mem->in(MemNode::Address);
       } else {
-        assert(mem->Opcode() == Op_EncodeISOArray, "sanity");
+        assert(mem->Opcode() == Op_EncodeISOArray ||
+               mem->Opcode() == Op_StrCompressedCopy, "sanity");
         adr = mem->in(3); // Destination array
       }
       const TypePtr* atype = adr->bottom_type()->is_ptr();
       int adr_idx = phase->C->get_alias_index(atype);
       if (adr_idx == alias_idx) {
-        assert(false, "Object is not scalar replaceable if a LoadStore node access its field");
+        DEBUG_ONLY(mem->dump();)
+        assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field");
+        return NULL;
+      }
+      mem = mem->in(MemNode::Memory);
+   } else if (mem->Opcode() == Op_StrInflatedCopy) {
+      Node* adr = mem->in(3); // Destination array
+      const TypePtr* atype = adr->bottom_type()->is_ptr();
+      int adr_idx = phase->C->get_alias_index(atype);
+      if (adr_idx == alias_idx) {
+        DEBUG_ONLY(mem->dump();)
+        assert(false, "Object is not scalar replaceable if a StrInflatedCopy node accesses its field");
         return NULL;
       }
       mem = mem->in(MemNode::Memory);
@@ -516,8 +528,10 @@
         }
         values.at_put(j, val);
       } else if (val->Opcode() == Op_SCMemProj) {
-        assert(val->in(0)->is_LoadStore() || val->in(0)->Opcode() == Op_EncodeISOArray, "sanity");
-        assert(false, "Object is not scalar replaceable if a LoadStore node access its field");
+        assert(val->in(0)->is_LoadStore() ||
+               val->in(0)->Opcode() == Op_EncodeISOArray ||
+               val->in(0)->Opcode() == Op_StrCompressedCopy, "sanity");
+        assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field");
         return NULL;
       } else if (val->is_ArrayCopy()) {
         Node* res = make_arraycopy_load(val->as_ArrayCopy(), offset, val->in(0), ft, phi_type, alloc);
@@ -779,10 +793,10 @@
   ciKlass* klass = NULL;
   ciInstanceKlass* iklass = NULL;
   int nfields = 0;
-  int array_base;
-  int element_size;
-  BasicType basic_elem_type;
-  ciType* elem_type;
+  int array_base = 0;
+  int element_size = 0;
+  BasicType basic_elem_type = T_ILLEGAL;
+  ciType* elem_type = NULL;
 
   Node* res = alloc->result_cast();
   assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result");
@@ -1305,10 +1319,10 @@
   // We need a Region and corresponding Phi's to merge the slow-path and fast-path results.
   // they will not be used if "always_slow" is set
   enum { slow_result_path = 1, fast_result_path = 2 };
-  Node *result_region;
-  Node *result_phi_rawmem;
-  Node *result_phi_rawoop;
-  Node *result_phi_i_o;
+  Node *result_region = NULL;
+  Node *result_phi_rawmem = NULL;
+  Node *result_phi_rawoop = NULL;
+  Node *result_phi_i_o = NULL;
 
   // The initial slow comparison is a size check, the comparison
   // we want to do is a BoolTest::gt
--- a/hotspot/src/share/vm/opto/matcher.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -936,9 +936,13 @@
     case Op_StrComp:
     case Op_StrEquals:
     case Op_StrIndexOf:
+    case Op_StrIndexOfChar:
     case Op_AryEq:
+    case Op_HasNegatives:
     case Op_MemBarVolatile:
     case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type?
+    case Op_StrInflatedCopy:
+    case Op_StrCompressedCopy:
     case Op_EncodeISOArray:
       nidx = Compile::AliasIdxTop;
       nat = NULL;
@@ -2156,7 +2160,11 @@
       case Op_StrComp:
       case Op_StrEquals:
       case Op_StrIndexOf:
+      case Op_StrIndexOfChar:
       case Op_AryEq:
+      case Op_HasNegatives:
+      case Op_StrInflatedCopy:
+      case Op_StrCompressedCopy:
       case Op_EncodeISOArray:
         set_shared(n); // Force result into register (it will be anyways)
         break;
@@ -2336,7 +2344,8 @@
         n->del_req(3);
         break;
       }
-      case Op_StrEquals: {
+      case Op_StrEquals:
+      case Op_StrIndexOfChar: {
         Node *pair1 = new BinaryNode(n->in(2),n->in(3));
         n->set_req(2,pair1);
         n->set_req(3,n->in(4));
@@ -2353,6 +2362,8 @@
         n->del_req(4);
         break;
       }
+      case Op_StrCompressedCopy:
+      case Op_StrInflatedCopy:
       case Op_EncodeISOArray: {
         // Restructure into a binary tree for Matching.
         Node* pair = new BinaryNode(n->in(3), n->in(4));
--- a/hotspot/src/share/vm/opto/memnode.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/memnode.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -997,7 +997,7 @@
 // "Acquire" - no following ref can move before (but earlier refs can
 // follow, like an early Load stalled in cache).  Requires multi-cpu
 // visibility.  Inserted independ of any load, as required
-// for intrinsic sun.misc.Unsafe.loadFence().
+// for intrinsic Unsafe.loadFence().
 class LoadFenceNode: public MemBarNode {
 public:
   LoadFenceNode(Compile* C, int alias_idx, Node* precedent)
@@ -1018,7 +1018,7 @@
 // "Release" - no earlier ref can move after (but later refs can move
 // up, like a speculative pipelined cache-hitting Load).  Requires
 // multi-cpu visibility.  Inserted independent of any store, as required
-// for intrinsic sun.misc.Unsafe.storeFence().
+// for intrinsic Unsafe.storeFence().
 class StoreFenceNode: public MemBarNode {
 public:
   StoreFenceNode(Compile* C, int alias_idx, Node* precedent)
--- a/hotspot/src/share/vm/opto/parse1.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -108,7 +108,7 @@
 
   // Very similar to LoadNode::make, except we handle un-aligned longs and
   // doubles on Sparc.  Intel can handle them just fine directly.
-  Node *l;
+  Node *l = NULL;
   switch (bt) {                // Signature is flattened
   case T_INT:     l = new LoadINode(ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInt::INT,        MemNode::unordered); break;
   case T_FLOAT:   l = new LoadFNode(ctl, mem, adr, TypeRawPtr::BOTTOM, Type::FLOAT,         MemNode::unordered); break;
@@ -1903,7 +1903,7 @@
   // Now use a Phi here for merging
   assert(!nocreate, "Cannot build a phi for a block already parsed.");
   const JVMState* jvms = map->jvms();
-  const Type* t;
+  const Type* t = NULL;
   if (jvms->is_loc(idx)) {
     t = block()->local_type_at(idx - jvms->locoff());
   } else if (jvms->is_stk(idx)) {
--- a/hotspot/src/share/vm/opto/runtime.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/runtime.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -264,7 +264,7 @@
   // Scavenge and allocate an instance.
   oop result;
 
-  if (array_type->oop_is_typeArray()) {
+  if (array_type->is_typeArray_klass()) {
     // The oopFactory likes to work with the element type.
     // (We could bypass the oopFactory, since it doesn't add much value.)
     BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type();
@@ -302,7 +302,7 @@
   // Scavenge and allocate an instance.
   oop result;
 
-  assert(array_type->oop_is_typeArray(), "should be called only for type array");
+  assert(array_type->is_typeArray_klass(), "should be called only for type array");
   // The oopFactory likes to work with the element type.
   BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type();
   result = oopFactory::new_typeArray_nozero(elem_type, len, THREAD);
--- a/hotspot/src/share/vm/opto/split_if.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/split_if.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -451,8 +451,8 @@
 
   // Replace both uses of 'new_iff' with Regions merging True/False
   // paths.  This makes 'new_iff' go dead.
-  Node *old_false, *old_true;
-  Node *new_false, *new_true;
+  Node *old_false = NULL, *old_true = NULL;
+  Node *new_false = NULL, *new_true = NULL;
   for (DUIterator_Last j2min, j2 = iff->last_outs(j2min); j2 >= j2min; --j2) {
     Node *ifp = iff->last_out(j2);
     assert( ifp->Opcode() == Op_IfFalse || ifp->Opcode() == Op_IfTrue, "" );
--- a/hotspot/src/share/vm/opto/stringopts.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/stringopts.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -598,7 +598,7 @@
   }
 
   // Collect the types needed to talk about the various slices of memory
-  char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS);
+  byte_adr_idx = C->get_alias_index(TypeAryPtr::BYTES);
 
   // For each locally allocated StringBuffer see if the usages can be
   // collapsed into a single String construction.
@@ -1128,6 +1128,25 @@
 }
 
 Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) {
+  if (arg->is_Con()) {
+    // Constant integer. Compute constant length using Integer.sizeTable
+    int arg_val = arg->get_int();
+    int count = 1;
+    if (arg_val < 0) {
+      arg_val = -arg_val;
+      count++;
+    }
+
+    ciArray* size_table = (ciArray*)size_table_field->constant_value().as_object();
+    for (int i = 0; i < size_table->length(); i++) {
+      if (arg_val <= size_table->element_value(i).as_int()) {
+        count += i;
+        break;
+      }
+    }
+    return __ intcon(count);
+  }
+
   RegionNode *final_merge = new RegionNode(3);
   kit.gvn().set_type(final_merge, Type::CONTROL);
   Node* final_size = new PhiNode(final_merge, TypeInt::INT);
@@ -1212,77 +1231,34 @@
   return final_size;
 }
 
-void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, Node* start, Node* end) {
-  RegionNode *final_merge = new RegionNode(4);
-  kit.gvn().set_type(final_merge, Type::CONTROL);
-  Node *final_mem = PhiNode::make(final_merge, kit.memory(char_adr_idx), Type::MEMORY, TypeAryPtr::CHARS);
-  kit.gvn().set_type(final_mem, Type::MEMORY);
-
-  // need to handle Integer.MIN_VALUE specially because negating doesn't make it positive
-  {
-    // i == MIN_VALUE
-    IfNode* iff = kit.create_and_map_if(kit.control(),
-                                        __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne),
-                                        PROB_FAIR, COUNT_UNKNOWN);
-
-    Node* old_mem = kit.memory(char_adr_idx);
-
-    kit.set_control(__ IfFalse(iff));
-    if (kit.stopped()) {
-      // Statically not equal to MIN_VALUE so this path is dead
-      final_merge->init_req(3, kit.control());
-    } else {
-      copy_string(kit, __ makecon(TypeInstPtr::make(C->env()->the_min_jint_string())),
-                  char_array, start);
-      final_merge->init_req(3, kit.control());
-      final_mem->init_req(3, kit.memory(char_adr_idx));
-    }
-
-    kit.set_control(__ IfTrue(iff));
-    kit.set_memory(old_mem, char_adr_idx);
-  }
-
-
-  // Simplified version of Integer.getChars
-
-  // int q, r;
-  // int charPos = index;
-  Node* charPos = end;
-
-  // char sign = 0;
-
-  Node* i = arg;
-  Node* sign = __ intcon(0);
-
+// Simplified version of Integer.getChars
+void PhaseStringOpts::getChars(GraphKit& kit, Node* arg, Node* dst_array, BasicType bt, Node* end, Node* final_merge, Node* final_mem, int merge_index) {
   // if (i < 0) {
   //     sign = '-';
   //     i = -i;
   // }
-  {
-    IfNode* iff = kit.create_and_map_if(kit.control(),
-                                        __ Bool(__ CmpI(arg, __ intcon(0)), BoolTest::lt),
-                                        PROB_FAIR, COUNT_UNKNOWN);
+  IfNode* iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(arg, __ intcon(0)), BoolTest::lt),
+                                      PROB_FAIR, COUNT_UNKNOWN);
 
-    RegionNode *merge = new RegionNode(3);
-    kit.gvn().set_type(merge, Type::CONTROL);
-    i = new PhiNode(merge, TypeInt::INT);
-    kit.gvn().set_type(i, TypeInt::INT);
-    sign = new PhiNode(merge, TypeInt::INT);
-    kit.gvn().set_type(sign, TypeInt::INT);
+  RegionNode* merge = new RegionNode(3);
+  kit.gvn().set_type(merge, Type::CONTROL);
+  Node* i = new PhiNode(merge, TypeInt::INT);
+  kit.gvn().set_type(i, TypeInt::INT);
+  Node* sign = new PhiNode(merge, TypeInt::INT);
+  kit.gvn().set_type(sign, TypeInt::INT);
 
-    merge->init_req(1, __ IfTrue(iff));
-    i->init_req(1, __ SubI(__ intcon(0), arg));
-    sign->init_req(1, __ intcon('-'));
-    merge->init_req(2, __ IfFalse(iff));
-    i->init_req(2, arg);
-    sign->init_req(2, __ intcon(0));
+  merge->init_req(1, __ IfTrue(iff));
+  i->init_req(1, __ SubI(__ intcon(0), arg));
+  sign->init_req(1, __ intcon('-'));
+  merge->init_req(2, __ IfFalse(iff));
+  i->init_req(2, arg);
+  sign->init_req(2, __ intcon(0));
 
-    kit.set_control(merge);
+  kit.set_control(merge);
 
-    C->record_for_igvn(merge);
-    C->record_for_igvn(i);
-    C->record_for_igvn(sign);
-  }
+  C->record_for_igvn(merge);
+  C->record_for_igvn(i);
+  C->record_for_igvn(sign);
 
   // for (;;) {
   //     q = i / 10;
@@ -1292,126 +1268,409 @@
   //     if (i == 0) break;
   // }
 
-  {
-    // Add loop predicate first.
-    kit.add_predicate();
+  // Add loop predicate first.
+  kit.add_predicate();
+
+  RegionNode* head = new RegionNode(3);
+  head->init_req(1, kit.control());
 
-    RegionNode *head = new RegionNode(3);
-    head->init_req(1, kit.control());
-    kit.gvn().set_type(head, Type::CONTROL);
-    Node *i_phi = new PhiNode(head, TypeInt::INT);
-    i_phi->init_req(1, i);
-    kit.gvn().set_type(i_phi, TypeInt::INT);
-    charPos = PhiNode::make(head, charPos);
-    kit.gvn().set_type(charPos, TypeInt::INT);
-    Node *mem = PhiNode::make(head, kit.memory(char_adr_idx), Type::MEMORY, TypeAryPtr::CHARS);
-    kit.gvn().set_type(mem, Type::MEMORY);
-    kit.set_control(head);
-    kit.set_memory(mem, char_adr_idx);
+  kit.gvn().set_type(head, Type::CONTROL);
+  Node* i_phi = new PhiNode(head, TypeInt::INT);
+  i_phi->init_req(1, i);
+  kit.gvn().set_type(i_phi, TypeInt::INT);
+  Node* charPos = new PhiNode(head, TypeInt::INT);
+  charPos->init_req(1, end);
+  kit.gvn().set_type(charPos, TypeInt::INT);
+  Node* mem = PhiNode::make(head, kit.memory(byte_adr_idx), Type::MEMORY, TypeAryPtr::BYTES);
+  kit.gvn().set_type(mem, Type::MEMORY);
 
-    Node* q = __ DivI(NULL, i_phi, __ intcon(10));
-    Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)),
-                                     __ LShiftI(q, __ intcon(1))));
-    Node* m1 = __ SubI(charPos, __ intcon(1));
-    Node* ch = __ AddI(r, __ intcon('0'));
-
-    Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR),
-                                  ch, T_CHAR, char_adr_idx, MemNode::unordered);
-
+  kit.set_control(head);
+  kit.set_memory(mem, byte_adr_idx);
 
-    IfNode* iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne),
-                                        PROB_FAIR, COUNT_UNKNOWN);
-    Node* ne = __ IfTrue(iff);
-    Node* eq = __ IfFalse(iff);
+  Node* q = __ DivI(kit.null(), i_phi, __ intcon(10));
+  Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)),
+                                   __ LShiftI(q, __ intcon(1))));
+  Node* index = __ SubI(charPos, __ intcon((bt == T_BYTE) ? 1 : 2));
+  Node* ch = __ AddI(r, __ intcon('0'));
+  Node* st = __ store_to_memory(kit.control(), kit.array_element_address(dst_array, index, T_BYTE),
+                                ch, bt, byte_adr_idx, MemNode::unordered);
 
-    head->init_req(2, ne);
-    mem->init_req(2, st);
-    i_phi->init_req(2, q);
-    charPos->init_req(2, m1);
-
-    charPos = m1;
+  iff = kit.create_and_map_if(head, __ Bool(__ CmpI(q, __ intcon(0)), BoolTest::ne),
+                              PROB_FAIR, COUNT_UNKNOWN);
+  Node* ne = __ IfTrue(iff);
+  Node* eq = __ IfFalse(iff);
 
-    kit.set_control(eq);
-    kit.set_memory(st, char_adr_idx);
+  head->init_req(2, ne);
+  mem->init_req(2, st);
+
+  i_phi->init_req(2, q);
+  charPos->init_req(2, index);
+  charPos = index;
 
-    C->record_for_igvn(head);
-    C->record_for_igvn(mem);
-    C->record_for_igvn(i_phi);
-    C->record_for_igvn(charPos);
-  }
+  kit.set_control(eq);
+  kit.set_memory(st, byte_adr_idx);
 
-  {
-    // if (sign != 0) {
-    //     buf [--charPos] = sign;
-    // }
-    IfNode* iff = kit.create_and_map_if(kit.control(),
-                                        __ Bool(__ CmpI(sign, __ intcon(0)), BoolTest::ne),
-                                        PROB_FAIR, COUNT_UNKNOWN);
+  C->record_for_igvn(head);
+  C->record_for_igvn(mem);
+  C->record_for_igvn(i_phi);
+  C->record_for_igvn(charPos);
 
-    final_merge->init_req(2, __ IfFalse(iff));
-    final_mem->init_req(2, kit.memory(char_adr_idx));
+  // if (sign != 0) {
+  //     buf [--charPos] = sign;
+  // }
+  iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(sign, __ intcon(0)), BoolTest::ne),
+                              PROB_FAIR, COUNT_UNKNOWN);
+
+  final_merge->init_req(merge_index + 2, __ IfFalse(iff));
+  final_mem->init_req(merge_index + 2, kit.memory(byte_adr_idx));
 
-    kit.set_control(__ IfTrue(iff));
-    if (kit.stopped()) {
-      final_merge->init_req(1, C->top());
-      final_mem->init_req(1, C->top());
-    } else {
-      Node* m1 = __ SubI(charPos, __ intcon(1));
-      Node* st = __ store_to_memory(kit.control(), kit.array_element_address(char_array, m1, T_CHAR),
-                                    sign, T_CHAR, char_adr_idx, MemNode::unordered);
+  kit.set_control(__ IfTrue(iff));
+  if (kit.stopped()) {
+    final_merge->init_req(merge_index + 1, C->top());
+    final_mem->init_req(merge_index + 1, C->top());
+  } else {
+    Node* index = __ SubI(charPos, __ intcon((bt == T_BYTE) ? 1 : 2));
+    st = __ store_to_memory(kit.control(), kit.array_element_address(dst_array, index, T_BYTE),
+                            sign, bt, byte_adr_idx, MemNode::unordered);
 
-      final_merge->init_req(1, kit.control());
-      final_mem->init_req(1, st);
-    }
-
-    kit.set_control(final_merge);
-    kit.set_memory(final_mem, char_adr_idx);
-
-    C->record_for_igvn(final_merge);
-    C->record_for_igvn(final_mem);
+    final_merge->init_req(merge_index + 1, kit.control());
+    final_mem->init_req(merge_index + 1, st);
   }
 }
 
+// Copy the characters representing arg into dst_array starting at start
+Node* PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* dst_array, Node* dst_coder, Node* start, Node* size) {
+  bool dcon = dst_coder->is_Con();
+  bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false;
+  Node* end = __ AddI(start, __ LShiftI(size, dst_coder));
 
-Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) {
-  Node* string = str;
-  Node* offset = kit.load_String_offset(kit.control(), string);
-  Node* count  = kit.load_String_length(kit.control(), string);
-  Node* value  = kit.load_String_value (kit.control(), string);
+  // The final_merge node has 4 entries in case the encoding is known:
+  // (0) Control, (1) result w/ sign, (2) result w/o sign, (3) result for Integer.min_value
+  // or 6 entries in case the encoding is not known:
+  // (0) Control, (1) Latin1 w/ sign, (2) Latin1 w/o sign, (3) min_value, (4) UTF16 w/ sign, (5) UTF16 w/o sign
+  RegionNode* final_merge = new RegionNode(dcon ? 4 : 6);
+  kit.gvn().set_type(final_merge, Type::CONTROL);
+
+  Node* final_mem = PhiNode::make(final_merge, kit.memory(byte_adr_idx), Type::MEMORY, TypeAryPtr::BYTES);
+  kit.gvn().set_type(final_mem, Type::MEMORY);
+
+  // need to handle arg == Integer.MIN_VALUE specially because negating doesn't make it positive
+  IfNode* iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(arg, __ intcon(0x80000000)), BoolTest::ne),
+                                      PROB_FAIR, COUNT_UNKNOWN);
+
+  Node* old_mem = kit.memory(byte_adr_idx);
+
+  kit.set_control(__ IfFalse(iff));
+  if (kit.stopped()) {
+    // Statically not equal to MIN_VALUE so this path is dead
+    final_merge->init_req(3, kit.control());
+  } else {
+    copy_string(kit, __ makecon(TypeInstPtr::make(C->env()->the_min_jint_string())),
+                dst_array, dst_coder, start);
+    final_merge->init_req(3, kit.control());
+    final_mem->init_req(3, kit.memory(byte_adr_idx));
+  }
+
+  kit.set_control(__ IfTrue(iff));
+  kit.set_memory(old_mem, byte_adr_idx);
+
+  if (!dcon) {
+    // Check encoding of destination
+    iff = kit.create_and_map_if(kit.control(), __ Bool(__ CmpI(dst_coder, __ intcon(0)), BoolTest::eq),
+                                PROB_FAIR, COUNT_UNKNOWN);
+    old_mem = kit.memory(byte_adr_idx);
+  }
+  if (!dcon || dbyte) {
+    // Destination is Latin1,
+    if (!dcon) {
+      kit.set_control(__ IfTrue(iff));
+    }
+    getChars(kit, arg, dst_array, T_BYTE, end, final_merge, final_mem);
+  }
+  if (!dcon || !dbyte) {
+    // Destination is UTF16
+    int merge_index = 0;
+    if (!dcon) {
+      kit.set_control(__ IfFalse(iff));
+      kit.set_memory(old_mem, byte_adr_idx);
+      merge_index = 3; // Account for Latin1 case
+    }
+    getChars(kit, arg, dst_array, T_CHAR, end, final_merge, final_mem, merge_index);
+  }
+
+  // Final merge point for Latin1 and UTF16 case
+  kit.set_control(final_merge);
+  kit.set_memory(final_mem, byte_adr_idx);
+
+  C->record_for_igvn(final_merge);
+  C->record_for_igvn(final_mem);
+  return end;
+}
+
+// Copy 'count' bytes/chars from src_array to dst_array starting at index start
+void PhaseStringOpts::arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array, Node* dst_array, BasicType elembt, Node* start, Node* count) {
+  assert(elembt == T_BYTE || elembt == T_CHAR, "Invalid type for arraycopy");
+
+  if (elembt == T_CHAR) {
+    // Get number of chars
+    count = __ RShiftI(count, __ intcon(1));
+  }
+
+  Node* extra = NULL;
+#ifdef _LP64
+  count = __ ConvI2L(count);
+  extra = C->top();
+#endif
+
+  Node* src_ptr = __ array_element_address(src_array, __ intcon(0), T_BYTE);
+  Node* dst_ptr = __ array_element_address(dst_array, start, T_BYTE);
+  // Check if destination address is aligned to HeapWordSize
+  const TypeInt* tdst = __ gvn().type(start)->is_int();
+  bool aligned = tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0);
+  // Figure out which arraycopy runtime method to call (disjoint, uninitialized).
+  const char* copyfunc_name = "arraycopy";
+  address     copyfunc_addr = StubRoutines::select_arraycopy_function(elembt, aligned, true, copyfunc_name, true);
+  ideal.make_leaf_call_no_fp(OptoRuntime::fast_arraycopy_Type(), copyfunc_addr, copyfunc_name,
+                             TypeAryPtr::BYTES, src_ptr, dst_ptr, count, extra);
+}
+
+#undef __
+#define __ ideal.
+
+// Copy contents of a Latin1 encoded string from src_array to dst_array
+void PhaseStringOpts::copy_latin1_string(GraphKit& kit, IdealKit& ideal, Node* src_array, IdealVariable& count,
+                                         Node* dst_array, Node* dst_coder, Node* start) {
+  bool dcon = dst_coder->is_Con();
+  bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false;
 
-  // copy the contents
-  if (offset->is_Con() && count->is_Con() && value->is_Con() && count->get_int() < unroll_string_copy_length) {
+  if (!dcon) {
+    __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1));
+  }
+  if (!dcon || dbyte) {
+    // Destination is Latin1. Simply emit a byte arraycopy.
+    arraycopy(kit, ideal, src_array, dst_array, T_BYTE, start, __ value(count));
+  }
+  if (!dcon) {
+    __ else_();
+  }
+  if (!dcon || !dbyte) {
+    // Destination is UTF16. Inflate src_array into dst_array.
+    kit.sync_kit(ideal);
+    if (Matcher::match_rule_supported(Op_StrInflatedCopy)) {
+      // Use fast intrinsic
+      Node* src = kit.array_element_address(src_array, kit.intcon(0), T_BYTE);
+      Node* dst = kit.array_element_address(dst_array, start, T_BYTE);
+      kit.inflate_string(src, dst, __ value(count));
+    } else {
+      // No intrinsic available, use slow method
+      kit.inflate_string_slow(src_array, dst_array, start, __ value(count));
+    }
+    ideal.sync_kit(&kit);
+    // Multiply count by two since we now need two bytes per char
+    __ set(count, __ LShiftI(__ value(count), __ ConI(1)));
+  }
+  if (!dcon) {
+    __ end_if();
+  }
+}
+
+// Read two bytes from index and index+1 and convert them to a char
+static jchar readChar(ciTypeArray* array, int index) {
+  int shift_high, shift_low;
+#ifdef VM_LITTLE_ENDIAN
+    shift_high = 0;
+    shift_low = 8;
+#else
+    shift_high = 8;
+    shift_low = 0;
+#endif
+
+  jchar b1 = ((jchar) array->byte_at(index)) & 0xff;
+  jchar b2 = ((jchar) array->byte_at(index+1)) & 0xff;
+  return (b1 << shift_high) | (b2 << shift_low);
+}
+
+// Copy contents of constant src_array to dst_array by emitting individual stores
+void PhaseStringOpts::copy_constant_string(GraphKit& kit, IdealKit& ideal, ciTypeArray* src_array, IdealVariable& count,
+                                           bool src_is_byte, Node* dst_array, Node* dst_coder, Node* start) {
+  bool dcon = dst_coder->is_Con();
+  bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false;
+  int length = src_array->length();
+
+  if (!dcon) {
+    __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1));
+  }
+  if (!dcon || dbyte) {
+    // Destination is Latin1. Copy each byte of src_array into dst_array.
+    Node* index = start;
+    for (int i = 0; i < length; i++) {
+      Node* adr = kit.array_element_address(dst_array, index, T_BYTE);
+      Node* val = __ ConI(src_array->byte_at(i));
+      __ store(__ ctrl(), adr, val, T_BYTE, byte_adr_idx, MemNode::unordered);
+      index = __ AddI(index, __ ConI(1));
+    }
+  }
+  if (!dcon) {
+    __ else_();
+  }
+  if (!dcon || !dbyte) {
+    // Destination is UTF16. Copy each char of src_array into dst_array.
+    Node* index = start;
+    for (int i = 0; i < length; i++) {
+      Node* adr = kit.array_element_address(dst_array, index, T_BYTE);
+      jchar val;
+      if (src_is_byte) {
+        val = src_array->byte_at(i) & 0xff;
+      } else {
+        val = readChar(src_array, i++);
+      }
+      __ store(__ ctrl(), adr, __ ConI(val), T_CHAR, byte_adr_idx, MemNode::unordered);
+      index = __ AddI(index, __ ConI(2));
+    }
+    if (src_is_byte) {
+      // Multiply count by two since we now need two bytes per char
+      __ set(count, __ ConI(2 * length));
+    }
+  }
+  if (!dcon) {
+    __ end_if();
+  }
+}
+
+// Compress copy contents of the byte/char String str into dst_array starting at index start.
+Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* dst_array, Node* dst_coder, Node* start) {
+  Node* src_array = kit.load_String_value(kit.control(), str);
+
+  IdealKit ideal(&kit, true, true);
+  IdealVariable count(ideal); __ declarations_done();
+
+  if (str->is_Con()) {
+    // Constant source string
+    const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr();
+    ciTypeArray* src_array_type = t->const_oop()->as_type_array();
+
+    // Check encoding of constant string
+    bool src_is_byte = (get_constant_coder(kit, str) == java_lang_String::CODER_LATIN1);
+
     // For small constant strings just emit individual stores.
     // A length of 6 seems like a good space/speed tradeof.
-    int c = count->get_int();
-    int o = offset->get_int();
-    const TypeOopPtr* t = kit.gvn().type(value)->isa_oopptr();
-    ciTypeArray* value_array = t->const_oop()->as_type_array();
-    for (int e = 0; e < c; e++) {
-      __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
-                         __ intcon(value_array->char_at(o + e)), T_CHAR, char_adr_idx,
-                         MemNode::unordered);
-      start = __ AddI(start, __ intcon(1));
+    __ set(count, __ ConI(src_array_type->length()));
+    int src_len = src_array_type->length() / (src_is_byte ? 1 : 2);
+    if (src_len < unroll_string_copy_length) {
+      // Small constant string
+      copy_constant_string(kit, ideal, src_array_type, count, src_is_byte, dst_array, dst_coder, start);
+    } else if (src_is_byte) {
+      // Source is Latin1
+      copy_latin1_string(kit, ideal, src_array, count, dst_array, dst_coder, start);
+    } else {
+      // Source is UTF16 (destination too). Simply emit a char arraycopy.
+      arraycopy(kit, ideal, src_array, dst_array, T_CHAR, start, __ value(count));
     }
   } else {
-    Node* src_ptr = kit.array_element_address(value, offset, T_CHAR);
-    Node* dst_ptr = kit.array_element_address(char_array, start, T_CHAR);
-    Node* c = count;
-    Node* extra = NULL;
-#ifdef _LP64
-    c = __ ConvI2L(c);
-    extra = C->top();
-#endif
-    Node* call = kit.make_runtime_call(GraphKit::RC_LEAF|GraphKit::RC_NO_FP,
-                                       OptoRuntime::fast_arraycopy_Type(),
-                                       CAST_FROM_FN_PTR(address, StubRoutines::jshort_disjoint_arraycopy()),
-                                       "jshort_disjoint_arraycopy", TypeAryPtr::CHARS,
-                                       src_ptr, dst_ptr, c, extra);
-    start = __ AddI(start, count);
+    Node* size = kit.load_array_length(src_array);
+    __ set(count, size);
+    // Non-constant source string
+    if (CompactStrings) {
+      // Emit runtime check for coder
+      Node* coder = kit.load_String_coder(__ ctrl(), str);
+      __ if_then(coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1)); {
+        // Source is Latin1
+        copy_latin1_string(kit, ideal, src_array, count, dst_array, dst_coder, start);
+      } __ else_();
+    }
+    // Source is UTF16 (destination too). Simply emit a char arraycopy.
+    arraycopy(kit, ideal, src_array, dst_array, T_CHAR, start, __ value(count));
+
+    if (CompactStrings) {
+      __ end_if();
+    }
   }
-  return start;
+
+  // Finally sync IdealKit and GraphKit.
+  kit.sync_kit(ideal);
+  return __ AddI(start, __ value(count));
 }
 
+// Compress copy the char into dst_array at index start.
+Node* PhaseStringOpts::copy_char(GraphKit& kit, Node* val, Node* dst_array, Node* dst_coder, Node* start) {
+  bool dcon = (dst_coder != NULL) && dst_coder->is_Con();
+  bool dbyte = dcon ? (dst_coder->get_int() == java_lang_String::CODER_LATIN1) : false;
+
+  IdealKit ideal(&kit, true, true);
+  IdealVariable end(ideal); __ declarations_done();
+  Node* adr = kit.array_element_address(dst_array, start, T_BYTE);
+  if (!dcon){
+    __ if_then(dst_coder, BoolTest::eq, __ ConI(java_lang_String::CODER_LATIN1));
+  }
+  if (!dcon || dbyte) {
+    // Destination is Latin1. Store a byte.
+    __ store(__ ctrl(), adr, val, T_BYTE, byte_adr_idx, MemNode::unordered);
+    __ set(end, __ AddI(start, __ ConI(1)));
+  }
+  if (!dcon) {
+    __ else_();
+  }
+  if (!dcon || !dbyte) {
+    // Destination is UTF16. Store a char.
+    __ store(__ ctrl(), adr, val, T_CHAR, byte_adr_idx, MemNode::unordered);
+    __ set(end, __ AddI(start, __ ConI(2)));
+  }
+  if (!dcon) {
+    __ end_if();
+  }
+  // Finally sync IdealKit and GraphKit.
+  kit.sync_kit(ideal);
+  return __ value(end);
+}
+
+#undef __
+#define __ kit.
+
+// Allocate a byte array of specified length.
+Node* PhaseStringOpts::allocate_byte_array(GraphKit& kit, IdealKit* ideal, Node* length) {
+  if (ideal != NULL) {
+    // Sync IdealKit and graphKit.
+    kit.sync_kit(*ideal);
+  }
+  Node* byte_array = NULL;
+  {
+    PreserveReexecuteState preexecs(&kit);
+    // The original jvms is for an allocation of either a String or
+    // StringBuffer so no stack adjustment is necessary for proper
+    // reexecution.  If we deoptimize in the slow path the bytecode
+    // will be reexecuted and the char[] allocation will be thrown away.
+    kit.jvms()->set_should_reexecute(true);
+    byte_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_BYTE))),
+                               length, 1);
+  }
+
+  // Mark the allocation so that zeroing is skipped since the code
+  // below will overwrite the entire array
+  AllocateArrayNode* byte_alloc = AllocateArrayNode::Ideal_array_allocation(byte_array, _gvn);
+  byte_alloc->maybe_set_complete(_gvn);
+
+  if (ideal != NULL) {
+    // Sync IdealKit and graphKit.
+    ideal->sync_kit(&kit);
+  }
+  return byte_array;
+}
+
+jbyte PhaseStringOpts::get_constant_coder(GraphKit& kit, Node* str) {
+  assert(str->is_Con(), "String must be constant");
+  const TypeOopPtr* str_type = kit.gvn().type(str)->isa_oopptr();
+  ciInstance* str_instance = str_type->const_oop()->as_instance();
+  jbyte coder = str_instance->field_value_by_offset(java_lang_String::coder_offset_in_bytes()).as_byte();
+  assert(CompactStrings || (coder == java_lang_String::CODER_UTF16), "Strings must be UTF16 encoded");
+  return coder;
+}
+
+int PhaseStringOpts::get_constant_length(GraphKit& kit, Node* str) {
+  assert(str->is_Con(), "String must be constant");
+  Node* src_array = kit.load_String_value(kit.control(), str);
+  const TypeOopPtr* t = kit.gvn().type(src_array)->isa_oopptr();
+  return t->const_oop()->as_type_array()->length();
+}
 
 void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
   // Log a little info about the transformation
@@ -1445,7 +1704,6 @@
   jvms->set_map(map);
   map->ensure_stack(jvms, jvms->method()->max_stack());
 
-
   // disconnect all the old StringBuilder calls from the graph
   sc->eliminate_unneeded_control();
 
@@ -1473,7 +1731,17 @@
   // are need for the copying phase.
   Node* string_sizes = new Node(args);
 
+  Node* coder = __ intcon(0);
   Node* length = __ intcon(0);
+  // If at least one argument is UTF16 encoded, we can fix the encoding.
+  bool coder_fixed = false;
+
+  if (!CompactStrings) {
+    // Fix encoding of result string to UTF16
+    coder_fixed = true;
+    coder = __ intcon(java_lang_String::CODER_UTF16);
+  }
+
   for (int argi = 0; argi < sc->num_arguments(); argi++) {
     Node* arg = sc->argument(argi);
     switch (sc->mode(argi)) {
@@ -1491,7 +1759,7 @@
         const Type* type = kit.gvn().type(arg);
         assert(type != TypePtr::NULL_PTR, "missing check");
         if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
-          // Null check with uncommont trap since
+          // Null check with uncommon trap since
           // StringBuilder(null) throws exception.
           // Use special uncommon trap instead of
           // calling normal do_null_check().
@@ -1509,11 +1777,13 @@
       case StringConcat::StringMode: {
         const Type* type = kit.gvn().type(arg);
         Node* count = NULL;
+        Node* arg_coder = NULL;
         if (type == TypePtr::NULL_PTR) {
           // replace the argument with the null checked version
           arg = null_string;
           sc->set_argument(argi, arg);
           count = kit.load_String_length(kit.control(), arg);
+          arg_coder = kit.load_String_coder(kit.control(), arg);
         } else if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
           // s = s != null ? s : "null";
           // length = length + (s.count - s.offset);
@@ -1537,11 +1807,32 @@
           arg = phi;
           sc->set_argument(argi, arg);
           count = kit.load_String_length(kit.control(), arg);
+          arg_coder = kit.load_String_coder(kit.control(), arg);
         } else {
           // A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP
           // kit.control might be a different test, that can be hoisted above the actual nullcheck
           // in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck.
           count = kit.load_String_length(NULL, arg);
+          arg_coder = kit.load_String_coder(NULL, arg);
+        }
+        if (arg->is_Con()) {
+          // Constant string. Get constant coder and length.
+          jbyte const_coder = get_constant_coder(kit, arg);
+          int const_length = get_constant_length(kit, arg);
+          if (const_coder == java_lang_String::CODER_LATIN1) {
+            // Can be latin1 encoded
+            arg_coder = __ intcon(const_coder);
+            count = __ intcon(const_length);
+          } else {
+            // Found UTF16 encoded string. Fix result array encoding to UTF16.
+            coder_fixed = true;
+            coder = __ intcon(const_coder);
+            count = __ intcon(const_length / 2);
+          }
+        }
+
+        if (!coder_fixed) {
+          coder = __ OrI(coder, arg_coder);
         }
         length = __ AddI(length, count);
         string_sizes->init_req(argi, NULL);
@@ -1549,6 +1840,34 @@
       }
       case StringConcat::CharMode: {
         // one character only
+        const TypeInt* t = kit.gvn().type(arg)->is_int();
+        if (!coder_fixed && t->is_con()) {
+          // Constant char
+          if (t->get_con() <= 255) {
+            // Can be latin1 encoded
+            coder = __ OrI(coder, __ intcon(java_lang_String::CODER_LATIN1));
+          } else {
+            // Must be UTF16 encoded. Fix result array encoding to UTF16.
+            coder_fixed = true;
+            coder = __ intcon(java_lang_String::CODER_UTF16);
+          }
+        } else if (!coder_fixed) {
+          // Not constant
+#undef __
+#define __ ideal.
+          IdealKit ideal(&kit, true, true);
+          IdealVariable char_coder(ideal); __ declarations_done();
+          // Check if character can be latin1 encoded
+          __ if_then(arg, BoolTest::le, __ ConI(0xFF));
+            __ set(char_coder, __ ConI(java_lang_String::CODER_LATIN1));
+          __ else_();
+            __ set(char_coder, __ ConI(java_lang_String::CODER_UTF16));
+          __ end_if();
+          kit.sync_kit(ideal);
+          coder = __ OrI(coder, __ value(char_coder));
+#undef __
+#define __ kit.
+        }
         length = __ AddI(length, __ intcon(1));
         break;
       }
@@ -1576,54 +1895,37 @@
 
   Node* result;
   if (!kit.stopped()) {
-    Node* char_array = NULL;
+    assert(CompactStrings || (coder->is_Con() && coder->get_int() == java_lang_String::CODER_UTF16),
+           "Result string must be UTF16 encoded if CompactStrings is disabled");
+
+    Node* dst_array = NULL;
     if (sc->num_arguments() == 1 &&
-          (sc->mode(0) == StringConcat::StringMode ||
-           sc->mode(0) == StringConcat::StringNullCheckMode)) {
+        (sc->mode(0) == StringConcat::StringMode ||
+         sc->mode(0) == StringConcat::StringNullCheckMode)) {
       // Handle the case when there is only a single String argument.
       // In this case, we can just pull the value from the String itself.
-      char_array = kit.load_String_value(kit.control(), sc->argument(0));
+      dst_array = kit.load_String_value(kit.control(), sc->argument(0));
     } else {
-      // length now contains the number of characters needed for the
-      // char[] so create a new AllocateArray for the char[]
-      {
-        PreserveReexecuteState preexecs(&kit);
-        // The original jvms is for an allocation of either a String or
-        // StringBuffer so no stack adjustment is necessary for proper
-        // reexecution.  If we deoptimize in the slow path the bytecode
-        // will be reexecuted and the char[] allocation will be thrown away.
-        kit.jvms()->set_should_reexecute(true);
-        char_array = kit.new_array(__ makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_CHAR))),
-                                   length, 1);
-      }
+      // Allocate destination byte array according to coder
+      dst_array = allocate_byte_array(kit, NULL, __ LShiftI(length, coder));
 
-      // Mark the allocation so that zeroing is skipped since the code
-      // below will overwrite the entire array
-      AllocateArrayNode* char_alloc = AllocateArrayNode::Ideal_array_allocation(char_array, _gvn);
-      char_alloc->maybe_set_complete(_gvn);
-
-      // Now copy the string representations into the final char[]
+      // Now copy the string representations into the final byte[]
       Node* start = __ intcon(0);
       for (int argi = 0; argi < sc->num_arguments(); argi++) {
         Node* arg = sc->argument(argi);
         switch (sc->mode(argi)) {
           case StringConcat::IntMode: {
-            Node* end = __ AddI(start, string_sizes->in(argi));
-            // getChars words backwards so pass the ending point as well as the start
-            int_getChars(kit, arg, char_array, start, end);
-            start = end;
+            start = int_getChars(kit, arg, dst_array, coder, start, string_sizes->in(argi));
             break;
           }
           case StringConcat::StringNullCheckMode:
           case StringConcat::StringMode: {
-            start = copy_string(kit, arg, char_array, start);
+            start = copy_string(kit, arg, dst_array, coder, start);
             break;
           }
           case StringConcat::CharMode: {
-            __ store_to_memory(kit.control(), kit.array_element_address(char_array, start, T_CHAR),
-                               arg, T_CHAR, char_adr_idx, MemNode::unordered);
-            start = __ AddI(start, __ intcon(1));
-            break;
+            start = copy_char(kit, arg, dst_array, coder, start);
+          break;
           }
           default:
             ShouldNotReachHere();
@@ -1642,12 +1944,9 @@
       result = kit.new_instance(__ makecon(TypeKlassPtr::make(C->env()->String_klass())));
     }
 
-    // Intialize the string
-    if (java_lang_String::has_offset_field()) {
-      kit.store_String_offset(kit.control(), result, __ intcon(0));
-      kit.store_String_length(kit.control(), result, length);
-    }
-    kit.store_String_value(kit.control(), result, char_array);
+    // Initialize the string
+    kit.store_String_value(kit.control(), result, dst_array);
+    kit.store_String_coder(kit.control(), result, coder);
   } else {
     result = C->top();
   }
--- a/hotspot/src/share/vm/opto/stringopts.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/stringopts.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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 "opto/phaseX.hpp"
 
 class StringConcat;
+class IdealVariable;
 
 class PhaseStringOpts : public Phase {
   friend class StringConcat;
@@ -40,7 +41,7 @@
   Unique_Node_List dead_worklist;
 
   // Memory slices needed for code gen
-  int char_adr_idx;
+  int byte_adr_idx;
 
   // Integer.sizeTable - used for int to String conversion
   ciField* size_table_field;
@@ -64,11 +65,37 @@
   // Compute the number of characters required to represent the int value
   Node* int_stringSize(GraphKit& kit, Node* value);
 
-  // Copy the characters representing value into char_array starting at start
-  void int_getChars(GraphKit& kit, Node* value, Node* char_array, Node* start, Node* end);
+  // Simplified version of Integer.getChars
+  void getChars(GraphKit& kit, Node* arg, Node* dst_array, BasicType bt, Node* end, Node* final_merge, Node* final_mem, int merge_index = 0);
+
+  // Copy the characters representing arg into dst_array starting at start
+  Node* int_getChars(GraphKit& kit, Node* arg, Node* dst_array, Node* dst_coder, Node* start, Node* size);
+
+  // Copy contents of the String str into dst_array starting at index start.
+  Node* copy_string(GraphKit& kit, Node* str, Node* dst_array, Node* dst_coder, Node* start);
+
+  // Copy 'count' bytes/chars from src_array to dst_array starting at index start
+  void arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array, Node* dst_array, BasicType elembt, Node* start, Node* count);
+
+  // Copy contents of constant src_array to dst_array by emitting individual stores
+  void copy_constant_string(GraphKit& kit, IdealKit& ideal, ciTypeArray* src_array, IdealVariable& count,
+                            bool src_is_byte, Node* dst_array, Node* dst_coder, Node* start);
 
-  // Copy of the contents of the String str into char_array starting at index start.
-  Node* copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start);
+  // Copy contents of a Latin1 encoded string from src_array to dst_array
+  void copy_latin1_string(GraphKit& kit, IdealKit& ideal, Node* src_array, IdealVariable& count,
+                          Node* dst_array, Node* dst_coder, Node* start);
+
+  // Copy the char into dst_array at index start.
+  Node* copy_char(GraphKit& kit, Node* val, Node* dst_array, Node* dst_coder, Node* start);
+
+  // Allocate a byte array of specified length.
+  Node* allocate_byte_array(GraphKit& kit, IdealKit* ideal, Node* length);
+
+  // Returns the coder of a constant string
+  jbyte get_constant_coder(GraphKit& kit, Node* str);
+
+  // Returns the length of a constant string
+  int get_constant_length(GraphKit& kit, Node* str);
 
   // Clean up any leftover nodes
   void record_dead_node(Node* node);
--- a/hotspot/src/share/vm/opto/superword.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -4001,7 +4001,7 @@
 }
 
 int SuperWord::mark_generations() {
-  Node *ii_err = 0, *tail_err;
+  Node *ii_err = NULL, *tail_err = NULL;
   for (int i = 0; i < _mem_slice_head.length(); i++) {
     Node* phi  = _mem_slice_head.at(i);
     assert(phi->is_Phi(), "must be phi");
--- a/hotspot/src/share/vm/prims/jni.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -563,7 +563,7 @@
   // return mirror for superclass
   Klass* super = k->java_super();
   // super2 is the value computed by the compiler's getSuperClass intrinsic:
-  debug_only(Klass* super2 = ( k->oop_is_array()
+  debug_only(Klass* super2 = ( k->is_array_klass()
                                  ? SystemDictionary::Object_klass()
                                  : k->super() ) );
   assert(super == super2,
@@ -1344,14 +1344,14 @@
   if (name == vmSymbols::object_initializer_name() ||
       name == vmSymbols::class_initializer_name()) {
     // Never search superclasses for constructors
-    if (klass->oop_is_instance()) {
+    if (klass->is_instance_klass()) {
       m = InstanceKlass::cast(klass())->find_method(name, signature);
     } else {
       m = NULL;
     }
   } else {
     m = klass->lookup_method(name, signature);
-    if (m == NULL &&  klass->oop_is_instance()) {
+    if (m == NULL &&  klass->is_instance_klass()) {
       m = InstanceKlass::cast(klass())->lookup_method_in_ordered_interfaces(name, signature);
     }
   }
@@ -2038,7 +2038,7 @@
   k()->initialize(CHECK_NULL);
 
   fieldDescriptor fd;
-  if (!k()->oop_is_instance() ||
+  if (!k()->is_instance_klass() ||
       !InstanceKlass::cast(k())->find_field(fieldname, signame, false, &fd)) {
     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
   }
@@ -2292,7 +2292,7 @@
   k()->initialize(CHECK_NULL);
 
   fieldDescriptor fd;
-  if (!k()->oop_is_instance() ||
+  if (!k()->is_instance_klass() ||
       !InstanceKlass::cast(k())->find_field(fieldname, signame, true, &fd)) {
     THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
   }
@@ -2474,12 +2474,18 @@
   typeArrayOop s_value = java_lang_String::value(s);
   if (s_value != NULL) {
     int s_len = java_lang_String::length(s);
-    int s_offset = java_lang_String::offset(s);
+    bool is_latin1 = java_lang_String::is_latin1(s);
     buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal);  // add one for zero termination
     /* JNI Specification states return NULL on OOM */
     if (buf != NULL) {
       if (s_len > 0) {
-        memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len);
+        if (!is_latin1) {
+          memcpy(buf, s_value->char_at_addr(0), sizeof(jchar)*s_len);
+        } else {
+          for (int i = 0; i < s_len; i++) {
+            buf[i] = ((jchar) s_value->byte_at(i)) & 0xff;
+          }
+        }
       }
       buf[s_len] = 0;
       //%note jni_5
@@ -3045,7 +3051,7 @@
  HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY(env, clazz);
   Klass* k   = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
   //%note jni_2
-  if (k->oop_is_instance()) {
+  if (k->is_instance_klass()) {
     for (int index = 0; index < InstanceKlass::cast(k)->methods()->length(); index++) {
       Method* m = InstanceKlass::cast(k)->methods()->at(index);
       if (m->is_native()) {
@@ -3118,9 +3124,15 @@
     THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
   } else {
     if (len > 0) {
-      int s_offset = java_lang_String::offset(s);
       typeArrayOop s_value = java_lang_String::value(s);
-      memcpy(buf, s_value->char_at_addr(s_offset+start), sizeof(jchar)*len);
+      bool is_latin1 = java_lang_String::is_latin1(s);
+      if (!is_latin1) {
+        memcpy(buf, s_value->char_at_addr(start), sizeof(jchar)*len);
+      } else {
+        for (int i = 0; i < len; i++) {
+          buf[i] = ((jchar) s_value->byte_at(i + start)) & 0xff;
+        }
+      }
     }
   }
 JNI_END
@@ -3186,18 +3198,23 @@
   JNIWrapper("GetStringCritical");
   HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(env, string, (uintptr_t *) isCopy);
   GC_locker::lock_critical(thread);
-  if (isCopy != NULL) {
-    *isCopy = JNI_FALSE;
-  }
   oop s = JNIHandles::resolve_non_null(string);
-  int s_len = java_lang_String::length(s);
   typeArrayOop s_value = java_lang_String::value(s);
-  int s_offset = java_lang_String::offset(s);
+  bool is_latin1 = java_lang_String::is_latin1(s);
+  if (isCopy != NULL) {
+    *isCopy = is_latin1 ? JNI_TRUE : JNI_FALSE;
+  }
   const jchar* ret;
-  if (s_len > 0) {
-    ret = s_value->char_at_addr(s_offset);
+  if (!is_latin1) {
+    ret = s_value->char_at_addr(0);
   } else {
-    ret = (jchar*) s_value->base(T_CHAR);
+    // Inflate latin1 encoded string to UTF16
+    int s_len = java_lang_String::length(s);
+    jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len, mtInternal);
+    for (int i = 0; i < s_len; i++) {
+      buf[i] = ((jchar) s_value->byte_at(i)) & 0xff;
+    }
+    ret = &buf[0];
   }
  HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN((uint16_t *) ret);
   return ret;
@@ -3207,7 +3224,14 @@
 JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars))
   JNIWrapper("ReleaseStringCritical");
   HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(env, str, (uint16_t *) chars);
-  // The str and chars arguments are ignored
+  // The str and chars arguments are ignored for UTF16 strings
+  oop s = JNIHandles::resolve_non_null(str);
+  bool is_latin1 = java_lang_String::is_latin1(s);
+  if (is_latin1) {
+    // For latin1 string, free jchar array allocated by earlier call to GetStringCritical.
+    // This assumes that ReleaseStringCritical bookends GetStringCritical.
+    FREE_C_HEAP_ARRAY(jchar, chars);
+  }
   GC_locker::unlock_critical(thread);
 HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN();
 JNI_END
@@ -3854,6 +3878,7 @@
   unit_test_function_call
 
 // Forward declaration
+void TestNmethodBucket_test();
 void test_semaphore();
 void TestOS_test();
 void TestReservedSpace_test();
@@ -3877,11 +3902,13 @@
 void FreeRegionList_test();
 void test_memset_with_concurrent_readers();
 void TestPredictions_test();
+void WorkerDataArray_test();
 #endif
 
 void execute_internal_vm_tests() {
   if (ExecuteInternalVMTests) {
     tty->print_cr("Running internal VM tests");
+    run_unit_test(TestNmethodBucket_test());
     run_unit_test(test_semaphore());
     run_unit_test(TestOS_test());
     run_unit_test(TestReservedSpace_test());
@@ -3922,6 +3949,7 @@
     }
     run_unit_test(test_memset_with_concurrent_readers());
     run_unit_test(TestPredictions_test());
+    run_unit_test(WorkerDataArray_test());
 #endif
     tty->print_cr("All internal VM tests passed");
   }
@@ -4063,6 +4091,10 @@
     OrderAccess::release_store(&vm_created, 0);
   }
 
+  // Flush stdout and stderr before exit.
+  fflush(stdout);
+  fflush(stderr);
+
   return result;
 
 }
--- a/hotspot/src/share/vm/prims/jniCheck.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jniCheck.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -514,7 +514,7 @@
   ASSERT_OOPS_ALLOWED;
   assert(klass != NULL, "klass argument must have a value");
 
-  if (!klass->oop_is_instance() ||
+  if (!klass->is_instance_klass() ||
       !InstanceKlass::cast(klass)->is_subclass_of(SystemDictionary::Throwable_klass())) {
     ReportJNIFatalError(thr, fatal_class_not_a_throwable_class);
   }
--- a/hotspot/src/share/vm/prims/jvm.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1022,10 +1022,10 @@
   KlassHandle klass(thread, java_lang_Class::as_Klass(mirror));
   // Figure size of result array
   int size;
-  if (klass->oop_is_instance()) {
+  if (klass->is_instance_klass()) {
     size = InstanceKlass::cast(klass())->local_interfaces()->length();
   } else {
-    assert(klass->oop_is_objArray() || klass->oop_is_typeArray(), "Illegal mirror klass");
+    assert(klass->is_objArray_klass() || klass->is_typeArray_klass(), "Illegal mirror klass");
     size = 2;
   }
 
@@ -1033,7 +1033,7 @@
   objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), size, CHECK_NULL);
   objArrayHandle result (THREAD, r);
   // Fill in result
-  if (klass->oop_is_instance()) {
+  if (klass->is_instance_klass()) {
     // Regular instance klass, fill in all local interfaces
     for (int index = 0; index < size; index++) {
       Klass* k = InstanceKlass::cast(klass())->local_interfaces()->at(index);
@@ -1056,7 +1056,7 @@
   }
   Klass* k = java_lang_Class::as_Klass(mirror);
   jboolean result = k->is_interface();
-  assert(!result || k->oop_is_instance(),
+  assert(!result || k->is_instance_klass(),
          "all interfaces are instance types");
   // The compiler intrinsic for isInterface tests the
   // Klass::_access_flags bits in the same way.
@@ -1097,7 +1097,7 @@
     // Signers are only set once, ClassLoader.java, and thus shouldn't
     // be called with an array.  Only the bootstrap loader creates arrays.
     Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       java_lang_Class::set_signers(k->java_mirror(), objArrayOop(JNIHandles::resolve(signers)));
     }
   }
@@ -1156,7 +1156,7 @@
 // Create an AccessControlContext with a protection domain with null codesource
 // and null permissions - which gives no permissions.
 oop create_dummy_access_control_context(TRAPS) {
-  InstanceKlass* pd_klass = InstanceKlass::cast(SystemDictionary::ProtectionDomain_klass());
+  InstanceKlass* pd_klass = SystemDictionary::ProtectionDomain_klass();
   Handle obj = pd_klass->allocate_instance_handle(CHECK_NULL);
   // Call constructor ProtectionDomain(null, null);
   JavaValue result(T_VOID);
@@ -1356,7 +1356,7 @@
 JVM_QUICK_ENTRY(jboolean, JVM_IsArrayClass(JNIEnv *env, jclass cls))
   JVMWrapper("JVM_IsArrayClass");
   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
-  return (k != NULL) && k->oop_is_array() ? true : false;
+  return (k != NULL) && k->is_array_klass() ? true : false;
 JVM_END
 
 
@@ -1389,7 +1389,7 @@
   // of an InstanceKlass
 
   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
-      ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_instance()) {
+      ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) {
     oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL);
     return (jobjectArray)JNIHandles::make_local(env, result);
   }
@@ -1453,7 +1453,7 @@
 {
   // ofClass is a reference to a java_lang_Class object.
   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
-      ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_instance()) {
+      ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) {
     return NULL;
   }
 
@@ -1471,7 +1471,7 @@
 {
   oop mirror = JNIHandles::resolve_non_null(cls);
   if (java_lang_Class::is_primitive(mirror) ||
-      !java_lang_Class::as_Klass(mirror)->oop_is_instance()) {
+      !java_lang_Class::as_Klass(mirror)->is_instance_klass()) {
     return NULL;
   }
   instanceKlassHandle k(THREAD, InstanceKlass::cast(java_lang_Class::as_Klass(mirror)));
@@ -1496,7 +1496,7 @@
   // Return null for arrays and primatives
   if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
     Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       Symbol* sym = InstanceKlass::cast(k)->generic_signature();
       if (sym == NULL) return NULL;
       Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
@@ -1514,7 +1514,7 @@
   // Return null for arrays and primitives
   if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
     Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->class_annotations(), CHECK_NULL);
       return (jbyteArray) JNIHandles::make_local(env, a);
     }
@@ -1584,7 +1584,7 @@
   // Return null for arrays and primitives
   if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
     Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations();
       if (type_annotations != NULL) {
         typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL);
@@ -1693,7 +1693,7 @@
 
   // Exclude primitive types and array types
   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
-      java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) {
+      java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) {
     // Return empty array
     oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL);
     return (jobjectArray) JNIHandles::make_local(env, res);
@@ -1767,7 +1767,7 @@
 
   // Exclude primitive types and array types
   if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass))
-      || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) {
+      || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) {
     // Return empty array
     oop res = oopFactory::new_objArray(klass, 0, CHECK_NULL);
     return (jobjectArray) JNIHandles::make_local(env, res);
@@ -1868,7 +1868,7 @@
   // Return null for primitives and arrays
   if (!java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) {
     Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       instanceKlassHandle k_h(THREAD, k);
       Handle jcp = sun_reflect_ConstantPool::create(CHECK_NULL);
       sun_reflect_ConstantPool::set_cp(jcp(), k_h->constants());
@@ -2136,8 +2136,8 @@
   if (java_lang_Class::is_primitive(r)) return false;
 
   Klass* k = java_lang_Class::as_Klass(r);
-  assert(k->oop_is_instance(), "must be an instance klass");
-  if (! k->oop_is_instance()) return false;
+  assert(k->is_instance_klass(), "must be an instance klass");
+  if (!k->is_instance_klass()) return false;
 
   ResourceMark rm(THREAD);
   const char* name = k->name()->as_C_string();
@@ -2182,12 +2182,12 @@
   k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
   // types will have length zero if this is not an InstanceKlass
   // (length is determined by call to JVM_GetClassCPEntriesCount)
-  if (k->oop_is_instance()) {
+  if (k->is_instance_klass()) {
     ConstantPool* cp = InstanceKlass::cast(k)->constants();
     for (int index = cp->length() - 1; index >= 0; index--) {
       constantTag tag = cp->tag_at(index);
       types[index] = (tag.is_unresolved_klass()) ? JVM_CONSTANT_Class : tag.value();
-  }
+    }
   }
 JVM_END
 
@@ -2196,9 +2196,7 @@
   JVMWrapper("JVM_GetClassCPEntriesCount");
   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
   k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
-  if (!k->oop_is_instance())
-    return 0;
-  return InstanceKlass::cast(k)->constants()->length();
+  return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->constants()->length();
 JVM_END
 
 
@@ -2206,9 +2204,7 @@
   JVMWrapper("JVM_GetClassFieldsCount");
   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
   k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
-  if (!k->oop_is_instance())
-    return 0;
-  return InstanceKlass::cast(k)->java_fields_count();
+  return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->java_fields_count();
 JVM_END
 
 
@@ -2216,9 +2212,7 @@
   JVMWrapper("JVM_GetClassMethodsCount");
   Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
   k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread);
-  if (!k->oop_is_instance())
-    return 0;
-  return InstanceKlass::cast(k)->methods()->length();
+  return (!k->is_instance_klass()) ? 0 : InstanceKlass::cast(k)->methods()->length();
 JVM_END
 
 
@@ -3476,7 +3470,7 @@
 
   KlassHandle klass_handle(THREAD, klass);
   // Check if we should initialize the class
-  if (init && klass_handle->oop_is_instance()) {
+  if (init && klass_handle->is_instance_klass()) {
     klass_handle->initialize(CHECK_NULL);
   }
   return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror());
@@ -3624,7 +3618,7 @@
     return NULL;
   }
   Klass* k = java_lang_Class::as_Klass(mirror());
-  if (!k->oop_is_instance()) {
+  if (!k->is_instance_klass()) {
     return NULL;
   }
   instanceKlassHandle ik_h(THREAD, k);
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -125,7 +125,7 @@
 // JVMSpec|     u2 attributes_count;
 // JVMSpec|     attribute_info attributes[attributes_count];
 // JVMSpec|   }
-void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
+void JvmtiClassFileReconstituter::write_code_attribute(const methodHandle& method) {
   ConstMethod* const_method = method->constMethod();
   u2 line_num_cnt = 0;
   int stackmap_len = 0;
@@ -415,7 +415,7 @@
 }
 
 // Compute size of LineNumberTable
-u2 JvmtiClassFileReconstituter::line_number_table_entries(methodHandle method) {
+u2 JvmtiClassFileReconstituter::line_number_table_entries(const methodHandle& method) {
   // The line number table is compressed so we don't know how big it is until decompressed.
   // Decompression is really fast so we just do it twice.
   u2 num_entries = 0;
@@ -435,7 +435,7 @@
 // JVMSpec|        u2 line_number;
 // JVMSpec|     } line_number_table[line_number_table_length];
 // JVMSpec|   }
-void JvmtiClassFileReconstituter::write_line_number_table_attribute(methodHandle method,
+void JvmtiClassFileReconstituter::write_line_number_table_attribute(const methodHandle& method,
                                                                     u2 num_entries) {
 
   write_attribute_name_index("LineNumberTable");
@@ -461,7 +461,7 @@
 // JVMSpec|       u2 index;
 // JVMSpec|     } local_variable_table[local_variable_table_length];
 // JVMSpec|   }
-void JvmtiClassFileReconstituter::write_local_variable_table_attribute(methodHandle method, u2 num_entries) {
+void JvmtiClassFileReconstituter::write_local_variable_table_attribute(const methodHandle& method, u2 num_entries) {
     write_attribute_name_index("LocalVariableTable");
     write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));
     write_u2(num_entries);
@@ -491,7 +491,7 @@
 // JVMSpec|       u2 index;
 // JVMSpec|     } local_variable_type_table[local_variable_type_table_length];
 // JVMSpec|   }
-void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(methodHandle method, u2 num_entries) {
+void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(const methodHandle& method, u2 num_entries) {
     write_attribute_name_index("LocalVariableTypeTable");
     write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));
     write_u2(num_entries);
@@ -519,7 +519,7 @@
 // JSR-202|     u2 number_of_entries;
 // JSR-202|     stack_map_frame_entries[number_of_entries];
 // JSR-202|   }
-void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle method,
+void JvmtiClassFileReconstituter::write_stackmap_table_attribute(const methodHandle& method,
                                                                  int stackmap_len) {
 
   write_attribute_name_index("StackMapTable");
@@ -538,7 +538,7 @@
 // JVMSpec|     u2 attributes_count;
 // JVMSpec|     attribute_info attributes[attributes_count];
 // JVMSpec|   }
-void JvmtiClassFileReconstituter::write_method_info(methodHandle method) {
+void JvmtiClassFileReconstituter::write_method_info(const methodHandle& method) {
   AccessFlags access_flags = method->access_flags();
   ConstMethod* const_method = method->constMethod();
   u2 generic_signature_index = const_method->generic_signature_index();
@@ -813,7 +813,7 @@
   Bytes::put_Java_u8(writeable_address(8), x);
 }
 
-void JvmtiClassFileReconstituter::copy_bytecodes(methodHandle mh,
+void JvmtiClassFileReconstituter::copy_bytecodes(const methodHandle& mh,
                                                  unsigned char* bytecodes) {
   // use a BytecodeStream to iterate over the bytecodes. JVM/fast bytecodes
   // and the breakpoint bytecode are converted to their original bytecodes.
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -110,18 +110,18 @@
   void write_class_file_format();
   void write_field_infos();
   void write_method_infos();
-  void write_method_info(methodHandle method);
-  void write_code_attribute(methodHandle method);
+  void write_method_info(const methodHandle& method);
+  void write_code_attribute(const methodHandle& method);
   void write_exceptions_attribute(ConstMethod* const_method);
   void write_synthetic_attribute();
   void write_class_attributes();
   void write_source_file_attribute();
   void write_source_debug_extension_attribute();
-  u2 line_number_table_entries(methodHandle method);
-  void write_line_number_table_attribute(methodHandle method, u2 num_entries);
-  void write_local_variable_table_attribute(methodHandle method, u2 num_entries);
-  void write_local_variable_type_table_attribute(methodHandle method, u2 num_entries);
-  void write_stackmap_table_attribute(methodHandle method, int stackmap_table_len);
+  u2 line_number_table_entries(const methodHandle& method);
+  void write_line_number_table_attribute(const methodHandle& method, u2 num_entries);
+  void write_local_variable_table_attribute(const methodHandle& method, u2 num_entries);
+  void write_local_variable_type_table_attribute(const methodHandle& method, u2 num_entries);
+  void write_stackmap_table_attribute(const methodHandle& method, int stackmap_table_len);
   u2 inner_classes_attribute_length();
   void write_inner_classes_attribute(int length);
   void write_signature_attribute(u2 generic_signaure_index);
@@ -150,7 +150,7 @@
 
   u1* class_file_bytes()      { return _buffer; }
 
-  static void copy_bytecodes(methodHandle method, unsigned char* bytecodes);
+  static void copy_bytecodes(const methodHandle& method, unsigned char* bytecodes);
 };
 
 #endif // SHARE_VM_PRIMS_JVMTICLASSFILERECONSTITUTER_HPP
--- a/hotspot/src/share/vm/prims/jvmtiEnter.xsl	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEnter.xsl	Wed Jul 05 21:00:20 2017 +0200
@@ -629,8 +629,8 @@
   jint trace_flags = JvmtiTrace::trace_flags(</xsl:text>
       <xsl:value-of select="@num"/>
       <xsl:text>);
-  const char *func_name;
-  const char *curr_thread_name;
+  const char *func_name = NULL;
+  const char *curr_thread_name = NULL;
   if (trace_flags) {
     func_name = JvmtiTrace::function_name(</xsl:text>
       <xsl:value-of select="@num"/>
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -966,7 +966,7 @@
     if (name() != NULL) {
       n = java_lang_String::as_utf8_string(name());
     } else {
-      n = UNICODE::as_utf8(NULL, 0);
+      n = UNICODE::as_utf8((jchar*) NULL, 0);
     }
 
     info_ptr->name = (char *) jvmtiMalloc(strlen(n)+1);
@@ -1187,15 +1187,14 @@
   Handle group_obj (current_thread, JNIHandles::resolve_external_guard(group));
   NULL_CHECK(group_obj(), JVMTI_ERROR_INVALID_THREAD_GROUP);
 
-  typeArrayHandle name;
+  const char* name;
   Handle parent_group;
   bool is_daemon;
   ThreadPriority max_priority;
 
   { MutexLocker mu(Threads_lock);
 
-    name         = typeArrayHandle(current_thread,
-                                   java_lang_ThreadGroup::name(group_obj()));
+    name         = java_lang_ThreadGroup::name(group_obj());
     parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(group_obj()));
     is_daemon    = java_lang_ThreadGroup::is_daemon(group_obj());
     max_priority = java_lang_ThreadGroup::maxPriority(group_obj());
@@ -1205,11 +1204,10 @@
   info_ptr->max_priority = max_priority;
   info_ptr->parent       = jni_reference(parent_group);
 
-  if (name() != NULL) {
-    const char* n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length());
-    info_ptr->name = (char *)jvmtiMalloc(strlen(n)+1);
+  if (name != NULL) {
+    info_ptr->name = (char*)jvmtiMalloc(strlen(name)+1);
     NULL_CHECK(info_ptr->name, JVMTI_ERROR_OUT_OF_MEMORY);
-    strcpy(info_ptr->name, n);
+    strcpy(info_ptr->name, name);
   } else {
     info_ptr->name = NULL;
   }
@@ -2139,7 +2137,7 @@
   }
   if (generic_ptr != NULL) {
     *generic_ptr = NULL;
-    if (!isPrimitive && k->oop_is_instance()) {
+    if (!isPrimitive && k->is_instance_klass()) {
       Symbol* soo = InstanceKlass::cast(k)->generic_signature();
       if (soo != NULL) {
         const char *gen_sig = soo->as_C_string();
@@ -2188,7 +2186,7 @@
   Klass* k_klass = java_lang_Class::as_Klass(k_mirror);
   NULL_CHECK(k_klass, JVMTI_ERROR_INVALID_CLASS);
 
-  if (!k_klass->oop_is_instance()) {
+  if (!k_klass->is_instance_klass()) {
     return JVMTI_ERROR_ABSENT_INFORMATION;
   }
 
@@ -2256,7 +2254,7 @@
     return JVMTI_ERROR_CLASS_NOT_PREPARED;
   }
 
-  if (!k->oop_is_instance()) {
+  if (!k->is_instance_klass()) {
     *method_count_ptr = 0;
     *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID));
     return JVMTI_ERROR_NONE;
@@ -2340,7 +2338,7 @@
     return JVMTI_ERROR_CLASS_NOT_PREPARED;
   }
 
-  if (!k->oop_is_instance()) {
+  if (!k->is_instance_klass()) {
     *field_count_ptr = 0;
     *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID));
     return JVMTI_ERROR_NONE;
@@ -2394,7 +2392,7 @@
     if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) ))
       return JVMTI_ERROR_CLASS_NOT_PREPARED;
 
-    if (!k->oop_is_instance()) {
+    if (!k->is_instance_klass()) {
       *interface_count_ptr = 0;
       *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass));
       return JVMTI_ERROR_NONE;
@@ -2528,7 +2526,7 @@
     bool result = false;
     if (!java_lang_Class::is_primitive(k_mirror)) {
       Klass* k = java_lang_Class::as_Klass(k_mirror);
-      if (k != NULL && k->oop_is_array()) {
+      if (k != NULL && k->is_array_klass()) {
         result = true;
       }
     }
@@ -2576,7 +2574,7 @@
     }
     Klass* k = java_lang_Class::as_Klass(k_mirror);
     NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS);
-    if (!k->oop_is_instance()) {
+    if (!k->is_instance_klass()) {
       return JVMTI_ERROR_ABSENT_INFORMATION;
     }
     char* sde = InstanceKlass::cast(k)->source_debug_extension();
@@ -3064,7 +3062,7 @@
     // in thread.cpp.
     JvmtiPendingMonitors::enter(rmonitor);
   } else {
-    int r;
+    int r = 0;
     Thread* thread = Thread::current();
 
     if (thread->is_Java_thread()) {
@@ -3127,7 +3125,7 @@
       err = JVMTI_ERROR_NOT_MONITOR_OWNER;
     }
   } else {
-    int r;
+    int r = 0;
     Thread* thread = Thread::current();
 
     if (thread->is_Java_thread()) {
@@ -3161,7 +3159,7 @@
 // rmonitor - pre-checked for validity
 jvmtiError
 JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) {
-  int r;
+  int r = 0;
   Thread* thread = Thread::current();
 
   if (thread->is_Java_thread()) {
@@ -3220,7 +3218,7 @@
 // rmonitor - pre-checked for validity
 jvmtiError
 JvmtiEnv::RawMonitorNotify(JvmtiRawMonitor * rmonitor) {
-  int r;
+  int r = 0;
   Thread* thread = Thread::current();
 
   if (thread->is_Java_thread()) {
@@ -3251,7 +3249,7 @@
 // rmonitor - pre-checked for validity
 jvmtiError
 JvmtiEnv::RawMonitorNotifyAll(JvmtiRawMonitor * rmonitor) {
-  int r;
+  int r = 0;
   Thread* thread = Thread::current();
 
   if (thread->is_Java_thread()) {
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -512,7 +512,7 @@
 // mean much better out of memory handling
 unsigned char *
 JvmtiEnvBase::jvmtiMalloc(jlong size) {
-  unsigned char* mem;
+  unsigned char* mem = NULL;
   jvmtiError result = allocate(size, &mem);
   assert(result == JVMTI_ERROR_NONE, "Allocate failed");
   return mem;
@@ -1032,7 +1032,7 @@
     // implied else: entry_count == 0
   }
 
-  jint nWant, nWait;
+  jint nWant = 0, nWait = 0;
   if (mon != NULL) {
     // this object has a heavyweight monitor
     nWant = mon->contentions(); // # of threads contending for monitor
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -104,7 +104,7 @@
         ClassLoaderData* cld = _scratch_classes[i]->class_loader_data();
         // Free the memory for this class at class unloading time.  Not before
         // because CMS might think this is still live.
-        cld->add_to_deallocate_list((InstanceKlass*)_scratch_classes[i]);
+        cld->add_to_deallocate_list(InstanceKlass::cast(_scratch_classes[i]));
       }
     }
     // Free os::malloc allocated memory in load_new_class_version.
@@ -199,7 +199,7 @@
   }
   Klass* the_class_oop = java_lang_Class::as_Klass(klass_mirror);
   // classes for arrays cannot be redefined
-  if (the_class_oop == NULL || !the_class_oop->oop_is_instance()) {
+  if (the_class_oop == NULL || !the_class_oop->is_instance_klass()) {
     return false;
   }
   return true;
@@ -216,7 +216,7 @@
 // referenced CP entries may already exist in *merge_cp_p in which case
 // there is nothing extra to append and only the current entry is
 // appended.
-void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp,
+void VM_RedefineClasses::append_entry(const constantPoolHandle& scratch_cp,
        int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p,
        TRAPS) {
 
@@ -336,7 +336,7 @@
       int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i,
                                                           merge_cp_p, merge_cp_length_p, THREAD);
 
-      const char *entry_name;
+      const char *entry_name = NULL;
       switch (scratch_cp->tag_at(scratch_i).value()) {
       case JVM_CONSTANT_Fieldref:
         entry_name = "Fieldref";
@@ -475,7 +475,7 @@
 } // end append_entry()
 
 
-int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp,
+int VM_RedefineClasses::find_or_append_indirect_entry(const constantPoolHandle& scratch_cp,
       int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
 
   int new_ref_i = ref_i;
@@ -507,7 +507,7 @@
 // Append a bootstrap specifier into the merge_cp operands that is semantically equal
 // to the scratch_cp operands bootstrap specifier passed by the old_bs_i index.
 // Recursively append new merge_cp entries referenced by the new bootstrap specifier.
-void VM_RedefineClasses::append_operand(constantPoolHandle scratch_cp, int old_bs_i,
+void VM_RedefineClasses::append_operand(const constantPoolHandle& scratch_cp, int old_bs_i,
        constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
 
   int old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i);
@@ -551,7 +551,7 @@
 } // end append_operand()
 
 
-int VM_RedefineClasses::find_or_append_operand(constantPoolHandle scratch_cp,
+int VM_RedefineClasses::find_or_append_operand(const constantPoolHandle& scratch_cp,
       int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
 
   int new_bs_i = old_bs_i; // bootstrap specifier index
@@ -577,7 +577,7 @@
 } // end find_or_append_operand()
 
 
-void VM_RedefineClasses::finalize_operands_merge(constantPoolHandle merge_cp, TRAPS) {
+void VM_RedefineClasses::finalize_operands_merge(const constantPoolHandle& merge_cp, TRAPS) {
   if (merge_cp->operands() == NULL) {
     return;
   }
@@ -910,8 +910,8 @@
 
 // Returns true if the current mismatch is due to a resolved/unresolved
 // class pair. Otherwise, returns false.
-bool VM_RedefineClasses::is_unresolved_class_mismatch(constantPoolHandle cp1,
-       int index1, constantPoolHandle cp2, int index2) {
+bool VM_RedefineClasses::is_unresolved_class_mismatch(const constantPoolHandle& cp1,
+       int index1, const constantPoolHandle& cp2, int index2) {
 
   jbyte t1 = cp1->tag_at(index1).value();
   if (t1 != JVM_CONSTANT_Class && t1 != JVM_CONSTANT_UnresolvedClass) {
@@ -1149,7 +1149,7 @@
 
 // Map old_index to new_index as needed. scratch_cp is only needed
 // for RC_TRACE() calls.
-void VM_RedefineClasses::map_index(constantPoolHandle scratch_cp,
+void VM_RedefineClasses::map_index(const constantPoolHandle& scratch_cp,
        int old_index, int new_index) {
   if (find_new_index(old_index) != 0) {
     // old_index is already mapped
@@ -1195,8 +1195,8 @@
 // scratch_cp to the corresponding entry in *merge_cp_p. Index map
 // entries are only created for entries in scratch_cp that occupy a
 // different location in *merged_cp_p.
-bool VM_RedefineClasses::merge_constant_pools(constantPoolHandle old_cp,
-       constantPoolHandle scratch_cp, constantPoolHandle *merge_cp_p,
+bool VM_RedefineClasses::merge_constant_pools(const constantPoolHandle& old_cp,
+       const constantPoolHandle& scratch_cp, constantPoolHandle *merge_cp_p,
        int *merge_cp_length_p, TRAPS) {
 
   if (merge_cp_p == NULL) {
@@ -1892,7 +1892,7 @@
   }
 
   u2 type_index = rewrite_cp_ref_in_annotation_data(annotations_typeArray,
-                    byte_i_ref, "mapped old type_index=%d", THREAD);
+                    byte_i_ref, "type_index", THREAD);
 
   u2 num_element_value_pairs = Bytes::get_Java_u2((address)
                                  annotations_typeArray->adr_at(byte_i_ref));
@@ -1915,7 +1915,7 @@
 
     u2 element_name_index = rewrite_cp_ref_in_annotation_data(
                               annotations_typeArray, byte_i_ref,
-                              "mapped old element_name_index=%d", THREAD);
+                              "element_name_index", THREAD);
 
     RC_TRACE_WITH_THREAD(0x02000000, THREAD,
       ("element_name_index=%d", element_name_index));
@@ -1939,8 +1939,6 @@
 // annotations_typeArray if needed. Returns the original constant
 // pool reference if a rewrite was not needed or the new constant
 // pool reference if a rewrite was needed.
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED
 u2 VM_RedefineClasses::rewrite_cp_ref_in_annotation_data(
      AnnotationArray* annotations_typeArray, int &byte_i_ref,
      const char * trace_mesg, TRAPS) {
@@ -1950,14 +1948,13 @@
   u2 old_cp_index = Bytes::get_Java_u2(cp_index_addr);
   u2 new_cp_index = find_new_index(old_cp_index);
   if (new_cp_index != 0) {
-    RC_TRACE_WITH_THREAD(0x02000000, THREAD, (trace_mesg, old_cp_index));
+    RC_TRACE_WITH_THREAD(0x02000000, THREAD, ("mapped old %s=%d", trace_mesg, old_cp_index));
     Bytes::put_Java_u2(cp_index_addr, new_cp_index);
     old_cp_index = new_cp_index;
   }
   byte_i_ref += 2;
   return old_cp_index;
 }
-PRAGMA_DIAG_POP
 
 
 // Rewrite constant pool references in the element_value portion of an
@@ -2022,7 +2019,7 @@
 
       u2 const_value_index = rewrite_cp_ref_in_annotation_data(
                                annotations_typeArray, byte_i_ref,
-                               "mapped old const_value_index=%d", THREAD);
+                               "const_value_index", THREAD);
 
       RC_TRACE_WITH_THREAD(0x02000000, THREAD,
         ("const_value_index=%d", const_value_index));
@@ -2041,11 +2038,11 @@
 
       u2 type_name_index = rewrite_cp_ref_in_annotation_data(
                              annotations_typeArray, byte_i_ref,
-                             "mapped old type_name_index=%d", THREAD);
+                             "type_name_index", THREAD);
 
       u2 const_name_index = rewrite_cp_ref_in_annotation_data(
                               annotations_typeArray, byte_i_ref,
-                              "mapped old const_name_index=%d", THREAD);
+                              "const_name_index", THREAD);
 
       RC_TRACE_WITH_THREAD(0x02000000, THREAD,
         ("type_name_index=%d  const_name_index=%d", type_name_index,
@@ -2065,7 +2062,7 @@
 
       u2 class_info_index = rewrite_cp_ref_in_annotation_data(
                               annotations_typeArray, byte_i_ref,
-                              "mapped old class_info_index=%d", THREAD);
+                              "class_info_index", THREAD);
 
       RC_TRACE_WITH_THREAD(0x02000000, THREAD,
         ("class_info_index=%d", class_info_index));
@@ -2867,7 +2864,7 @@
 // }
 //
 void VM_RedefineClasses::rewrite_cp_refs_in_stack_map_table(
-       methodHandle method, TRAPS) {
+       const methodHandle& method, TRAPS) {
 
   if (!method->has_stackmap_table()) {
     return;
@@ -3339,10 +3336,10 @@
 
   // If the class being redefined is java.lang.Object, we need to fix all
   // array class vtables also
-  if (k->oop_is_array() && _the_class_oop == SystemDictionary::Object_klass()) {
+  if (k->is_array_klass() && _the_class_oop == SystemDictionary::Object_klass()) {
     k->vtable()->adjust_method_entries(the_class, &trace_name_printed);
 
-  } else if (k->oop_is_instance()) {
+  } else if (k->is_instance_klass()) {
     HandleMark hm(_thread);
     InstanceKlass *ik = InstanceKlass::cast(k);
 
@@ -3379,7 +3376,7 @@
     // default_vtable_indices for methods already in the vtable.
     // If redefining Unsafe, walk all the vtables looking for entries.
     if (ik->vtable_length() > 0 && (_the_class_oop->is_interface()
-        || _the_class_oop == SystemDictionary::misc_Unsafe_klass()
+        || _the_class_oop == SystemDictionary::internal_Unsafe_klass()
         || ik->is_subtype_of(_the_class_oop))) {
       // ik->vtable() creates a wrapper object; rm cleans it up
       ResourceMark rm(_thread);
@@ -3396,7 +3393,7 @@
     // subclass relationship between an interface and an InstanceKlass.
     // If redefining Unsafe, walk all the itables looking for entries.
     if (ik->itable_length() > 0 && (_the_class_oop->is_interface()
-        || _the_class_oop == SystemDictionary::misc_Unsafe_klass()
+        || _the_class_oop == SystemDictionary::internal_Unsafe_klass()
         || ik->is_subclass_of(_the_class_oop))) {
       // ik->itable() creates a wrapper object; rm cleans it up
       ResourceMark rm(_thread);
@@ -3443,7 +3440,7 @@
 
 // Clean method data for this class
 void VM_RedefineClasses::MethodDataCleaner::do_klass(Klass* k) {
-  if (k->oop_is_instance()) {
+  if (k->is_instance_klass()) {
     InstanceKlass *ik = InstanceKlass::cast(k);
     // Clean MethodData of this class's methods so they don't refer to
     // old methods that are no longer running.
@@ -4131,9 +4128,9 @@
 
   for (Klass *subk = ik->subklass(); subk != NULL;
        subk = subk->next_sibling()) {
-    if (subk->oop_is_instance()) {
+    if (subk->is_instance_klass()) {
       // Only update instanceKlasses
-      InstanceKlass *subik = (InstanceKlass*)subk;
+      InstanceKlass *subik = InstanceKlass::cast(subk);
       // recursively do subclasses of the current subclass
       increment_class_counter(subik, THREAD);
     }
@@ -4158,7 +4155,7 @@
     no_old_methods = false;
   }
 
-  if (k->oop_is_instance()) {
+  if (k->is_instance_klass()) {
     HandleMark hm(_thread);
     InstanceKlass *ik = InstanceKlass::cast(k);
 
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -420,23 +420,23 @@
   void increment_class_counter(InstanceKlass *ik, TRAPS);
 
   // Support for constant pool merging (these routines are in alpha order):
-  void append_entry(constantPoolHandle scratch_cp, int scratch_i,
+  void append_entry(const constantPoolHandle& scratch_cp, int scratch_i,
     constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
-  void append_operand(constantPoolHandle scratch_cp, int scratch_bootstrap_spec_index,
+  void append_operand(const constantPoolHandle& scratch_cp, int scratch_bootstrap_spec_index,
     constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
-  void finalize_operands_merge(constantPoolHandle merge_cp, TRAPS);
-  int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i,
+  void finalize_operands_merge(const constantPoolHandle& merge_cp, TRAPS);
+  int find_or_append_indirect_entry(const constantPoolHandle& scratch_cp, int scratch_i,
     constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
-  int find_or_append_operand(constantPoolHandle scratch_cp, int scratch_bootstrap_spec_index,
+  int find_or_append_operand(const constantPoolHandle& scratch_cp, int scratch_bootstrap_spec_index,
     constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS);
   int find_new_index(int old_index);
   int find_new_operand_index(int old_bootstrap_spec_index);
-  bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1,
-    constantPoolHandle cp2, int index2);
-  void map_index(constantPoolHandle scratch_cp, int old_index, int new_index);
+  bool is_unresolved_class_mismatch(const constantPoolHandle& cp1, int index1,
+    const constantPoolHandle& cp2, int index2);
+  void map_index(const constantPoolHandle& scratch_cp, int old_index, int new_index);
   void map_operand_index(int old_bootstrap_spec_index, int new_bootstrap_spec_index);
-  bool merge_constant_pools(constantPoolHandle old_cp,
-    constantPoolHandle scratch_cp, constantPoolHandle *merge_cp_p,
+  bool merge_constant_pools(const constantPoolHandle& old_cp,
+    const constantPoolHandle& scratch_cp, constantPoolHandle *merge_cp_p,
     int *merge_cp_length_p, TRAPS);
   jvmtiError merge_cp_and_rewrite(instanceKlassHandle the_class,
     instanceKlassHandle scratch_class, TRAPS);
@@ -480,7 +480,7 @@
     instanceKlassHandle scratch_class, TRAPS);
   bool rewrite_cp_refs_in_methods_type_annotations(
     instanceKlassHandle scratch_class, TRAPS);
-  void rewrite_cp_refs_in_stack_map_table(methodHandle method, TRAPS);
+  void rewrite_cp_refs_in_stack_map_table(const methodHandle& method, TRAPS);
   void rewrite_cp_refs_in_verification_type_info(
          address& stackmap_addr_ref, address stackmap_end, u2 frame_i,
          u1 frame_size, TRAPS);
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -588,7 +588,7 @@
     _obj_tag = (_entry == NULL) ? 0 : _entry->tag();
 
     // get the class and the class's tag value
-    assert(InstanceKlass::cast(SystemDictionary::Class_klass())->is_mirror_instance_klass(), "Is not?");
+    assert(SystemDictionary::Class_klass()->is_mirror_instance_klass(), "Is not?");
 
     _klass_tag = tag_for(tag_map, _o->klass()->java_mirror());
   }
@@ -1057,21 +1057,36 @@
   // get the string value and length
   // (string value may be offset from the base)
   int s_len = java_lang_String::length(str);
-  int s_offset = java_lang_String::offset(str);
+  bool is_latin1 = java_lang_String::is_latin1(str);
   jchar* value;
   if (s_len > 0) {
-    value = s_value->char_at_addr(s_offset);
+    if (!is_latin1) {
+      value = s_value->char_at_addr(0);
+    } else {
+      // Inflate latin1 encoded string to UTF16
+      jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len, mtInternal);
+      for (int i = 0; i < s_len; i++) {
+        buf[i] = ((jchar) s_value->byte_at(i)) & 0xff;
+      }
+      value = &buf[0];
+    }
   } else {
+    // Don't use char_at_addr(0) if length is 0
     value = (jchar*) s_value->base(T_CHAR);
   }
 
   // invoke the callback
-  return (*cb)(wrapper->klass_tag(),
-               wrapper->obj_size(),
-               wrapper->obj_tag_p(),
-               value,
-               (jint)s_len,
-               user_data);
+  jint res = (*cb)(wrapper->klass_tag(),
+                   wrapper->obj_size(),
+                   wrapper->obj_tag_p(),
+                   value,
+                   (jint)s_len,
+                   user_data);
+
+  if (is_latin1 && s_len > 0) {
+    FREE_C_HEAP_ARRAY(jchar, value);
+  }
+  return res;
 }
 
 // helper function to invoke string primitive value callback
@@ -1118,7 +1133,7 @@
   Klass* klass = java_lang_Class::as_Klass(obj);
 
   // ignore classes for object and type arrays
-  if (!klass->oop_is_instance()) {
+  if (!klass->is_instance_klass()) {
     return 0;
   }
 
@@ -2569,7 +2584,7 @@
       // SystemDictionary::always_strong_oops_do reports the application
       // class loader as a root. We want this root to be reported as
       // a root kind of "OTHER" rather than "SYSTEM_CLASS".
-      if (!o->is_instanceMirror()) {
+      if (!o->is_instance() || !InstanceKlass::cast(o->klass())->is_mirror_instance_klass()) {
         kind = JVMTI_HEAP_REFERENCE_OTHER;
       }
     }
@@ -2821,7 +2836,7 @@
   int i;
   Klass* klass = java_lang_Class::as_Klass(java_class);
 
-  if (klass->oop_is_instance()) {
+  if (klass->is_instance_klass()) {
     InstanceKlass* ik = InstanceKlass::cast(klass);
 
     // Ignore the class if it hasn't been initialized yet
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -148,7 +148,7 @@
     oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
     int slot  = java_lang_reflect_Field::slot(target_oop);  // fd.index()
     KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
-    if (!k.is_null() && k->oop_is_instance()) {
+    if (!k.is_null() && k->is_instance_klass()) {
       fieldDescriptor fd(InstanceKlass::cast(k()), slot);
       oop mname2 = init_field_MemberName(mname, fd);
       if (mname2 != NULL) {
@@ -164,7 +164,7 @@
     oop clazz  = java_lang_reflect_Method::clazz(target_oop);
     int slot   = java_lang_reflect_Method::slot(target_oop);
     KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
-    if (!k.is_null() && k->oop_is_instance()) {
+    if (!k.is_null() && k->is_instance_klass()) {
       Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
       if (m == NULL || is_signature_polymorphic(m->intrinsic_id()))
         return NULL;            // do not resolve unless there is a concrete signature
@@ -175,7 +175,7 @@
     oop clazz  = java_lang_reflect_Constructor::clazz(target_oop);
     int slot   = java_lang_reflect_Constructor::slot(target_oop);
     KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
-    if (!k.is_null() && k->oop_is_instance()) {
+    if (!k.is_null() && k->is_instance_klass()) {
       Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
       if (m == NULL)  return NULL;
       CallInfo info(m, k());
@@ -637,8 +637,8 @@
   {
     Klass* defc_klass = java_lang_Class::as_Klass(defc_oop());
     if (defc_klass == NULL)  return empty;  // a primitive; no resolution possible
-    if (!defc_klass->oop_is_instance()) {
-      if (!defc_klass->oop_is_array())  return empty;
+    if (!defc_klass->is_instance_klass()) {
+      if (!defc_klass->is_array_klass())  return empty;
       defc_klass = SystemDictionary::Object_klass();
     }
     defc = instanceKlassHandle(THREAD, defc_klass);
@@ -804,7 +804,7 @@
   case IS_FIELD:
     {
       assert(vmtarget->is_klass(), "field vmtarget is Klass*");
-      if (!((Klass*) vmtarget)->oop_is_instance())  break;
+      if (!((Klass*) vmtarget)->is_instance_klass())  break;
       instanceKlassHandle defc(THREAD, (Klass*) vmtarget);
       DEBUG_ONLY(vmtarget = NULL);  // safety
       bool is_static = ((flags & JVM_ACC_STATIC) != 0);
@@ -841,7 +841,7 @@
 
   Thread* thread = Thread::current();
 
-  if (k.is_null() || !k->oop_is_instance())  return -1;
+  if (k.is_null() || !k->is_instance_klass())  return -1;
 
   int rfill = 0, rlimit = results->length(), rskip = skip;
   // overflow measurement:
@@ -1164,12 +1164,12 @@
   if (VerifyMethodHandles && caller_jh != NULL &&
       java_lang_invoke_MemberName::clazz(mname()) != NULL) {
     Klass* reference_klass = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname()));
-    if (reference_klass != NULL && reference_klass->oop_is_objArray()) {
+    if (reference_klass != NULL && reference_klass->is_objArray_klass()) {
       reference_klass = ObjArrayKlass::cast(reference_klass)->bottom_klass();
     }
 
     // Reflection::verify_class_access can only handle instance classes.
-    if (reference_klass != NULL && reference_klass->oop_is_instance()) {
+    if (reference_klass != NULL && reference_klass->is_instance_klass()) {
       // Emulate LinkResolver::check_klass_accessability.
       Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
       if (!Reflection::verify_class_access(caller,
--- a/hotspot/src/share/vm/prims/nativeLookup.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/nativeLookup.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -67,7 +67,7 @@
 }
 
 
-char* NativeLookup::pure_jni_name(methodHandle method) {
+char* NativeLookup::pure_jni_name(const methodHandle& method) {
   stringStream st;
   // Prefix
   st.print("Java_");
@@ -80,7 +80,7 @@
 }
 
 
-char* NativeLookup::critical_jni_name(methodHandle method) {
+char* NativeLookup::critical_jni_name(const methodHandle& method) {
   stringStream st;
   // Prefix
   st.print("JavaCritical_");
@@ -93,7 +93,7 @@
 }
 
 
-char* NativeLookup::long_jni_name(methodHandle method) {
+char* NativeLookup::long_jni_name(const methodHandle& method) {
   // Signature ignore the wrapping parenteses and the trailing return type
   stringStream st;
   Symbol* signature = method->signature();
@@ -121,6 +121,7 @@
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
 
 static JNINativeMethod lookup_special_native_methods[] = {
+  { CC"Java_jdk_internal_misc_Unsafe_registerNatives",             NULL, FN_PTR(JVM_RegisterUnsafeMethods)       },
   { CC"Java_sun_misc_Unsafe_registerNatives",                      NULL, FN_PTR(JVM_RegisterUnsafeMethods)       },
   { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
   { CC"Java_sun_misc_Perf_registerNatives",                        NULL, FN_PTR(JVM_RegisterPerfMethods)         },
@@ -142,7 +143,7 @@
   return NULL;
 }
 
-address NativeLookup::lookup_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS) {
+address NativeLookup::lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS) {
   address entry;
   // Compute complete JNI name for style
   stringStream st;
@@ -199,7 +200,7 @@
 }
 
 
-address NativeLookup::lookup_critical_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style) {
+address NativeLookup::lookup_critical_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style) {
   if (!method->has_native_function()) {
     return NULL;
   }
@@ -229,7 +230,7 @@
 
 // Check all the formats of native implementation name to see if there is one
 // for the specified method.
-address NativeLookup::lookup_entry(methodHandle method, bool& in_base_library, TRAPS) {
+address NativeLookup::lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS) {
   address entry = NULL;
   in_base_library = false;
   // Compute pure name
@@ -264,7 +265,7 @@
 
 // Check all the formats of native implementation name to see if there is one
 // for the specified method.
-address NativeLookup::lookup_critical_entry(methodHandle method) {
+address NativeLookup::lookup_critical_entry(const methodHandle& method) {
   if (!CriticalJNINatives) return NULL;
 
   if (method->is_synchronized() ||
@@ -318,7 +319,7 @@
 // If any are found, remove them before attemping the look up of the
 // native implementation again.
 // See SetNativeMethodPrefix in the JVM TI Spec for more details.
-address NativeLookup::lookup_entry_prefixed(methodHandle method, bool& in_base_library, TRAPS) {
+address NativeLookup::lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS) {
 #if INCLUDE_JVMTI
   ResourceMark rm(THREAD);
 
@@ -354,7 +355,7 @@
   return NULL;
 }
 
-address NativeLookup::lookup_base(methodHandle method, bool& in_base_library, TRAPS) {
+address NativeLookup::lookup_base(const methodHandle& method, bool& in_base_library, TRAPS) {
   address entry = NULL;
   ResourceMark rm(THREAD);
 
@@ -372,7 +373,7 @@
 }
 
 
-address NativeLookup::lookup(methodHandle method, bool& in_base_library, TRAPS) {
+address NativeLookup::lookup(const methodHandle& method, bool& in_base_library, TRAPS) {
   if (!method->has_native_function()) {
     address entry = lookup_base(method, in_base_library, CHECK_NULL);
     method->set_native_function(entry,
--- a/hotspot/src/share/vm/prims/nativeLookup.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/nativeLookup.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,20 +34,20 @@
 class NativeLookup : AllStatic {
  private:
   // JNI name computation
-  static char* pure_jni_name(methodHandle method);
-  static char* long_jni_name(methodHandle method);
-  static char* critical_jni_name(methodHandle method);
+  static char* pure_jni_name(const methodHandle& method);
+  static char* long_jni_name(const methodHandle& method);
+  static char* critical_jni_name(const methodHandle& method);
 
   // Style specific lookup
-  static address lookup_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS);
-  static address lookup_critical_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style);
-  static address lookup_base (methodHandle method, bool& in_base_library, TRAPS);
-  static address lookup_entry(methodHandle method, bool& in_base_library, TRAPS);
-  static address lookup_entry_prefixed(methodHandle method, bool& in_base_library, TRAPS);
+  static address lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS);
+  static address lookup_critical_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style);
+  static address lookup_base (const methodHandle& method, bool& in_base_library, TRAPS);
+  static address lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS);
+  static address lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS);
  public:
   // Lookup native function. May throw UnsatisfiedLinkError.
-  static address lookup(methodHandle method, bool& in_base_library, TRAPS);
-  static address lookup_critical_entry(methodHandle method);
+  static address lookup(const methodHandle& method, bool& in_base_library, TRAPS);
+  static address lookup_critical_entry(const methodHandle& method);
 
   // Lookup native functions in base library.
   static address base_library_lookup(const char* class_name, const char* method_name, const char* signature);
--- a/hotspot/src/share/vm/prims/unsafe.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/unsafe.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -45,7 +45,7 @@
 #endif // INCLUDE_ALL_GCS
 
 /*
- *      Implementation of class sun.misc.Unsafe
+ *      Implementation of class Unsafe
  */
 
 
@@ -766,12 +766,12 @@
   }
   oop      mirror = JNIHandles::resolve_non_null(acls);
   Klass* k      = java_lang_Class::as_Klass(mirror);
-  if (k == NULL || !k->oop_is_array()) {
+  if (k == NULL || !k->is_array_klass()) {
     THROW(vmSymbols::java_lang_InvalidClassException());
-  } else if (k->oop_is_objArray()) {
+  } else if (k->is_objArray_klass()) {
     base  = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
     scale = heapOopSize;
-  } else if (k->oop_is_typeArray()) {
+  } else if (k->is_typeArray_klass()) {
     TypeArrayKlass* tak = TypeArrayKlass::cast(k);
     base  = tak->array_header_in_bytes();
     assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
@@ -783,7 +783,7 @@
 
 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls))
   UnsafeWrapper("Unsafe_ArrayBaseOffset");
-  int base, scale;
+  int base = 0, scale = 0;
   getBaseAndScale(base, scale, acls, CHECK_0);
   return field_offset_from_byte_offset(base);
 UNSAFE_END
@@ -791,7 +791,7 @@
 
 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls))
   UnsafeWrapper("Unsafe_ArrayIndexScale");
-  int base, scale;
+  int base = 0, scale = 0;
   getBaseAndScale(base, scale, acls, CHECK_0);
   // This VM packs both fields and array elements down to the byte.
   // But watch out:  If this changes, so that array references for
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1028,17 +1028,19 @@
   CodeBlobStub(const CodeBlob* blob) :
       name(os::strdup(blob->name())),
       size(blob->size()),
-      blob_type(WhiteBox::get_blob_type(blob)) { }
+      blob_type(WhiteBox::get_blob_type(blob)),
+      address((jlong) blob) { }
   ~CodeBlobStub() { os::free((void*) name); }
   const char* const name;
-  const int         size;
-  const int         blob_type;
+  const jint        size;
+  const jint        blob_type;
+  const jlong       address;
 };
 
 static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) {
   jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
   CHECK_JNI_EXCEPTION_(env, NULL);
-  jobjectArray result = env->NewObjectArray(3, clazz, NULL);
+  jobjectArray result = env->NewObjectArray(4, clazz, NULL);
 
   jstring name = env->NewStringUTF(cb->name);
   CHECK_JNI_EXCEPTION_(env, NULL);
@@ -1052,6 +1054,10 @@
   CHECK_JNI_EXCEPTION_(env, NULL);
   env->SetObjectArrayElement(result, 2, obj);
 
+  obj = longBox(thread, env, cb->address);
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  env->SetObjectArrayElement(result, 3, obj);
+
   return result;
 }
 
@@ -1092,9 +1098,9 @@
   CHECK_JNI_EXCEPTION_(env, NULL);
   env->SetObjectArrayElement(result, 3, id);
 
-  jobject address = longBox(thread, env, (jlong) code);
+  jobject entry_point = longBox(thread, env, (jlong) code->entry_point());
   CHECK_JNI_EXCEPTION_(env, NULL);
-  env->SetObjectArrayElement(result, 4, address);
+  env->SetObjectArrayElement(result, 4, entry_point);
 
   return result;
 WB_END
@@ -1275,9 +1281,9 @@
   VMThread::execute(&force_safepoint_op);
 WB_END
 
-WB_ENTRY(long, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass))
+WB_ENTRY(jlong, WB_GetConstantPool(JNIEnv* env, jobject wb, jclass klass))
   instanceKlassHandle ikh(java_lang_Class::as_Klass(JNIHandles::resolve(klass)));
-  return (long) ikh->constants();
+  return (jlong) ikh->constants();
 WB_END
 
 template <typename T>
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -467,14 +467,14 @@
 }
 
 // Update the rate and submit compile
-void AdvancedThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) {
+void AdvancedThresholdPolicy::submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) {
   int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count();
   update_rate(os::javaTimeMillis(), mh());
   CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", thread);
 }
 
 // Handle the invocation event.
-void AdvancedThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh,
+void AdvancedThresholdPolicy::method_invocation_event(const methodHandle& mh, const methodHandle& imh,
                                                       CompLevel level, nmethod* nm, JavaThread* thread) {
   if (should_create_mdo(mh(), level)) {
     create_mdo(mh, thread);
@@ -489,7 +489,7 @@
 
 // Handle the back branch event. Notice that we can compile the method
 // with a regular entry from here.
-void AdvancedThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh,
+void AdvancedThresholdPolicy::method_back_branch_event(const methodHandle& mh, const methodHandle& imh,
                                                        int bci, CompLevel level, nmethod* nm, JavaThread* thread) {
   if (should_create_mdo(mh(), level)) {
     create_mdo(mh, thread);
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -213,11 +213,11 @@
   jlong start_time() const     { return _start_time; }
 
   // Submit a given method for compilation (and update the rate).
-  virtual void submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread);
+  virtual void submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread);
   // event() from SimpleThresholdPolicy would call these.
-  virtual void method_invocation_event(methodHandle method, methodHandle inlinee,
+  virtual void method_invocation_event(const methodHandle& method, const methodHandle& inlinee,
                                        CompLevel level, nmethod* nm, JavaThread* thread);
-  virtual void method_back_branch_event(methodHandle method, methodHandle inlinee,
+  virtual void method_back_branch_event(const methodHandle& method, const methodHandle& inlinee,
                                         int bci, CompLevel level, nmethod* nm, JavaThread* thread);
 public:
   AdvancedThresholdPolicy() : _start_time(0) { }
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1120,7 +1120,7 @@
                                  Flag::Flags origin) {
   JDK_Version since = JDK_Version();
 
-  if (parse_argument(arg, origin) || ignore_unrecognized) {
+  if (parse_argument(arg, origin)) {
     return true;
   }
 
@@ -1156,7 +1156,7 @@
   Flag* found_flag = Flag::find_flag((const char*)argname, arg_len, true, true);
   if (found_flag != NULL) {
     char locked_message_buf[BUFLEN];
-    found_flag->get_locked_message(locked_message_buf, BUFLEN);
+    Flag::MsgType msg_type = found_flag->get_locked_message(locked_message_buf, BUFLEN);
     if (strlen(locked_message_buf) == 0) {
       if (found_flag->is_bool() && !has_plus_minus) {
         jio_fprintf(defaultStream::error_stream(),
@@ -1169,9 +1169,19 @@
           "Improperly specified VM option '%s'\n", argname);
       }
     } else {
+#ifdef PRODUCT
+      bool mismatched = ((msg_type == Flag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD) ||
+                         (msg_type == Flag::DEVELOPER_FLAG_BUT_PRODUCT_BUILD));
+      if (ignore_unrecognized && mismatched) {
+        return true;
+      }
+#endif
       jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf);
     }
   } else {
+    if (ignore_unrecognized) {
+      return true;
+    }
     jio_fprintf(defaultStream::error_stream(),
                 "Unrecognized VM option '%s'\n", argname);
     Flag* fuzzy_matched = Flag::fuzzy_match((const char*)argname, arg_len, true);
@@ -2469,16 +2479,6 @@
     }
   }
 
-  // Note: only executed in non-PRODUCT mode
-  if (!UseAsyncConcMarkSweepGC &&
-      (ExplicitGCInvokesConcurrent ||
-       ExplicitGCInvokesConcurrentAndUnloadsClasses)) {
-    jio_fprintf(defaultStream::error_stream(),
-                "error: +ExplicitGCInvokesConcurrent[AndUnloadsClasses] conflicts"
-                " with -UseAsyncConcMarkSweepGC");
-    status = false;
-  }
-
   if (PrintNMTStatistics) {
 #if INCLUDE_NMT
     if (MemTracker::tracking_level() == NMT_off) {
@@ -3481,33 +3481,8 @@
   sprintf(path, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep);
 
 #if INCLUDE_JVMCI
-  jint res = JVMCIRuntime::save_options(_system_properties);
-  if (res != JNI_OK) {
-    return res;
-  }
-
   if (EnableJVMCI) {
-    // Append lib/jvmci/*.jar to boot class path
-    char jvmciDir[JVM_MAXPATHLEN];
-    const char* fileSep = os::file_separator();
-    jio_snprintf(jvmciDir, sizeof(jvmciDir), "%s%slib%sjvmci", Arguments::get_java_home(), fileSep, fileSep);
-    DIR* dir = os::opendir(jvmciDir);
-    if (dir != NULL) {
-      struct dirent *entry;
-      char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(jvmciDir), mtInternal);
-      while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
-        const char* name = entry->d_name;
-        const char* ext = name + strlen(name) - 4;
-        if (ext > name && strcmp(ext, ".jar") == 0) {
-          char fileName[JVM_MAXPATHLEN];
-          jio_snprintf(fileName, sizeof(fileName), "%s%s%s", jvmciDir, fileSep, name);
-          scp_p->add_suffix(fileName);
-          scp_assembly_required = true;
-        }
-      }
-      FREE_C_HEAP_ARRAY(char, dbuf);
-      os::closedir(dir);
-    }
+    JVMCIRuntime::save_options(_system_properties);
   }
 #endif // INCLUDE_JVMCI
 
@@ -3858,6 +3833,7 @@
 
     JavaVMOption option;
     option.optionString = opt_hd;
+    option.extraInfo = NULL;
 
     options->append(option);                // Fill in option
 
--- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -218,7 +218,7 @@
   return 0;
 }
 
-void NonTieredCompPolicy::reset_counter_for_invocation_event(methodHandle m) {
+void NonTieredCompPolicy::reset_counter_for_invocation_event(const methodHandle& m) {
   // Make sure invocation and backedge counter doesn't overflow again right away
   // as would be the case for native methods.
 
@@ -232,7 +232,7 @@
   assert(!m->was_never_executed(), "don't reset to 0 -- could be mistaken for never-executed");
 }
 
-void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) {
+void NonTieredCompPolicy::reset_counter_for_back_branch_event(const methodHandle& m) {
   // Delay next back-branch event but pump up invocation counter to trigger
   // whole method compilation.
   MethodCounters* mcs = m->method_counters();
@@ -283,7 +283,7 @@
                                         CounterHalfLifeTime);
   for (int i = 0; i < classes_per_tick; i++) {
     Klass* k = SystemDictionary::try_get_next_class();
-    if (k != NULL && k->oop_is_instance()) {
+    if (k != NULL && k->is_instance_klass()) {
       InstanceKlass::cast(k)->methods_do(do_method);
     }
   }
@@ -357,7 +357,7 @@
   return (current >= initial + target);
 }
 
-nmethod* NonTieredCompPolicy::event(methodHandle method, methodHandle inlinee, int branch_bci,
+nmethod* NonTieredCompPolicy::event(const methodHandle& method, const methodHandle& inlinee, int branch_bci,
                                     int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) {
   assert(comp_level == CompLevel_none, "This should be only called from the interpreter");
   NOT_PRODUCT(trace_frequency_counter_overflow(method, branch_bci, bci));
@@ -416,22 +416,18 @@
 }
 
 #ifndef PRODUCT
-PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
-void NonTieredCompPolicy::trace_frequency_counter_overflow(methodHandle m, int branch_bci, int bci) {
+void NonTieredCompPolicy::trace_frequency_counter_overflow(const methodHandle& m, int branch_bci, int bci) {
   if (TraceInvocationCounterOverflow) {
     MethodCounters* mcs = m->method_counters();
     assert(mcs != NULL, "MethodCounters cannot be NULL for profiling");
     InvocationCounter* ic = mcs->invocation_counter();
     InvocationCounter* bc = mcs->backedge_counter();
     ResourceMark rm;
-    const char* msg =
-      bci == InvocationEntryBci
-      ? "comp-policy cntr ovfl @ %d in entry of "
-      : "comp-policy cntr ovfl @ %d in loop of ";
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-    tty->print(msg, bci);
-PRAGMA_DIAG_POP
+    if (bci == InvocationEntryBci) {
+      tty->print("comp-policy cntr ovfl @ %d in entry of ", bci);
+    } else {
+      tty->print("comp-policy cntr ovfl @ %d in loop of ", bci);
+    }
     m->print_value();
     tty->cr();
     ic->print();
@@ -448,7 +444,7 @@
   }
 }
 
-void NonTieredCompPolicy::trace_osr_request(methodHandle method, nmethod* osr, int bci) {
+void NonTieredCompPolicy::trace_osr_request(const methodHandle& method, nmethod* osr, int bci) {
   if (TraceOnStackReplacement) {
     ResourceMark rm;
     tty->print(osr != NULL ? "Reused OSR entry for " : "Requesting OSR entry for ");
@@ -460,7 +456,7 @@
 
 // SimpleCompPolicy - compile current method
 
-void SimpleCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) {
+void SimpleCompPolicy::method_invocation_event(const methodHandle& m, JavaThread* thread) {
   const int comp_level = CompLevel_highest_tier;
   const int hot_count = m->invocation_count();
   reset_counter_for_invocation_event(m);
@@ -474,7 +470,7 @@
   }
 }
 
-void SimpleCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) {
+void SimpleCompPolicy::method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) {
   const int comp_level = CompLevel_highest_tier;
   const int hot_count = m->backedge_count();
   const char* comment = "backedge_count";
@@ -491,7 +487,7 @@
 
 
 // Consider m for compilation
-void StackWalkCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) {
+void StackWalkCompPolicy::method_invocation_event(const methodHandle& m, JavaThread* thread) {
   const int comp_level = CompLevel_highest_tier;
   const int hot_count = m->invocation_count();
   reset_counter_for_invocation_event(m);
@@ -530,7 +526,7 @@
   }
 }
 
-void StackWalkCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) {
+void StackWalkCompPolicy::method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) {
   const int comp_level = CompLevel_highest_tier;
   const int hot_count = m->backedge_count();
   const char* comment = "backedge_count";
@@ -663,7 +659,7 @@
 }
 
 
-const char* StackWalkCompPolicy::shouldInline(methodHandle m, float freq, int cnt) {
+const char* StackWalkCompPolicy::shouldInline(const methodHandle& m, float freq, int cnt) {
   // Allows targeted inlining
   // positive filter: should send be inlined?  returns NULL (--> yes)
   // or rejection msg
@@ -690,7 +686,7 @@
 }
 
 
-const char* StackWalkCompPolicy::shouldNotInline(methodHandle m) {
+const char* StackWalkCompPolicy::shouldNotInline(const methodHandle& m) {
   // negative filter: should send NOT be inlined?  returns NULL (--> inline) or rejection msg
   if (m->is_abstract()) return (_msg = "abstract method");
   // note: we allow ik->is_abstract()
--- a/hotspot/src/share/vm/runtime/compilationPolicy.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,7 +66,7 @@
   virtual int compiler_count(CompLevel comp_level) = 0;
   // main notification entry, return a pointer to an nmethod if the OSR is required,
   // returns NULL otherwise.
-  virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) = 0;
+  virtual nmethod* event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) = 0;
   // safepoint() is called at the end of the safepoint
   virtual void do_safepoint_work() = 0;
   // reprofile request
@@ -91,11 +91,11 @@
 class NonTieredCompPolicy : public CompilationPolicy {
   int _compiler_count;
 protected:
-  static void trace_frequency_counter_overflow(methodHandle m, int branch_bci, int bci);
-  static void trace_osr_request(methodHandle method, nmethod* osr, int bci);
+  static void trace_frequency_counter_overflow(const methodHandle& m, int branch_bci, int bci);
+  static void trace_osr_request(const methodHandle& method, nmethod* osr, int bci);
   static void trace_osr_completion(nmethod* osr_nm);
-  void reset_counter_for_invocation_event(methodHandle method);
-  void reset_counter_for_back_branch_event(methodHandle method);
+  void reset_counter_for_invocation_event(const methodHandle& method);
+  void reset_counter_for_back_branch_event(const methodHandle& method);
 public:
   NonTieredCompPolicy() : _compiler_count(0) { }
   virtual CompLevel initial_compile_level() { return CompLevel_highest_tier; }
@@ -107,15 +107,15 @@
   virtual bool is_mature(Method* method);
   virtual void initialize();
   virtual CompileTask* select_task(CompileQueue* compile_queue);
-  virtual nmethod* event(methodHandle method, methodHandle inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread);
-  virtual void method_invocation_event(methodHandle m, JavaThread* thread) = 0;
-  virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread) = 0;
+  virtual nmethod* event(const methodHandle& method, const methodHandle& inlinee, int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread);
+  virtual void method_invocation_event(const methodHandle& m, JavaThread* thread) = 0;
+  virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) = 0;
 };
 
 class SimpleCompPolicy : public NonTieredCompPolicy {
  public:
-  virtual void method_invocation_event(methodHandle m, JavaThread* thread);
-  virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread);
+  virtual void method_invocation_event(const methodHandle& m, JavaThread* thread);
+  virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread);
 };
 
 // StackWalkCompPolicy - existing C2 policy
@@ -123,8 +123,8 @@
 #ifdef COMPILER2
 class StackWalkCompPolicy : public NonTieredCompPolicy {
  public:
-  virtual void method_invocation_event(methodHandle m, JavaThread* thread);
-  virtual void method_back_branch_event(methodHandle m, int bci, JavaThread* thread);
+  virtual void method_invocation_event(const methodHandle& m, JavaThread* thread);
+  virtual void method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread);
 
  private:
   RFrame* findTopInlinableFrame(GrowableArray<RFrame*>* stack);
@@ -134,9 +134,9 @@
   // they are used for performance debugging only (print better messages)
   static const char* _msg;            // reason for not inlining
 
-  static const char* shouldInline   (methodHandle callee, float frequency, int cnt);
+  static const char* shouldInline   (const methodHandle& callee, float frequency, int cnt);
   // positive filter: should send be inlined?  returns NULL (--> yes) or rejection msg
-  static const char* shouldNotInline(methodHandle callee);
+  static const char* shouldNotInline(const methodHandle& callee);
   // negative filter: should send NOT be inlined?  returns NULL (--> inline) or rejection msg
 
 };
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -758,15 +758,15 @@
     KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()));
     oop obj = NULL;
 
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       InstanceKlass* ik = InstanceKlass::cast(k());
       obj = ik->allocate_instance(THREAD);
-    } else if (k->oop_is_typeArray()) {
+    } else if (k->is_typeArray_klass()) {
       TypeArrayKlass* ak = TypeArrayKlass::cast(k());
       assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length");
       int len = sv->field_size() / type2size[ak->element_type()];
       obj = ak->allocate(len, THREAD);
-    } else if (k->oop_is_objArray()) {
+    } else if (k->is_objArray_klass()) {
       ObjArrayKlass* ak = ObjArrayKlass::cast(k());
       obj = ak->allocate(sv->field_size(), THREAD);
     }
@@ -1010,13 +1010,13 @@
       continue;
     }
 
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       InstanceKlass* ik = InstanceKlass::cast(k());
       reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj(), skip_internal);
-    } else if (k->oop_is_typeArray()) {
+    } else if (k->is_typeArray_klass()) {
       TypeArrayKlass* ak = TypeArrayKlass::cast(k());
       reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type());
-    } else if (k->oop_is_objArray()) {
+    } else if (k->is_objArray_klass()) {
       reassign_object_array_elements(fr, reg_map, sv, (objArrayOop) obj());
     }
   }
@@ -1345,7 +1345,7 @@
 }
 
 #if defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI
-void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS) {
+void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS) {
   // in case of an unresolved klass entry, load the class.
   if (constant_pool->tag_at(index).is_unresolved_klass()) {
     Klass* tk = constant_pool->klass_at_ignore_error(index, CHECK);
@@ -1376,7 +1376,7 @@
 }
 
 
-void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index) {
+void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index) {
   EXCEPTION_MARK;
   load_class_by_index(constant_pool, index, THREAD);
   if (HAS_PENDING_EXCEPTION) {
@@ -1461,14 +1461,14 @@
         oop speculation_log = nm->speculation_log();
         if (speculation_log != NULL) {
           if (TraceDeoptimization || TraceUncollectedSpeculations) {
-            if (SpeculationLog::lastFailed(speculation_log) != NULL) {
+            if (HotSpotSpeculationLog::lastFailed(speculation_log) != NULL) {
               tty->print_cr("A speculation that was not collected by the compiler is being overwritten");
             }
           }
           if (TraceDeoptimization) {
             tty->print_cr("Saving speculation to speculation log");
           }
-          SpeculationLog::set_lastFailed(speculation_log, speculation);
+          HotSpotSpeculationLog::set_lastFailed(speculation_log, speculation);
         } else {
           if (TraceDeoptimization) {
             tty->print_cr("Speculation present but no speculation log");
--- a/hotspot/src/share/vm/runtime/deoptimization.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/deoptimization.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -420,8 +420,8 @@
                                                bool& ret_maybe_prior_trap,
                                                bool& ret_maybe_prior_recompile);
   // class loading support for uncommon trap
-  static void load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS);
-  static void load_class_by_index(constantPoolHandle constant_pool, int index);
+  static void load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS);
+  static void load_class_by_index(const constantPoolHandle& constant_pool, int index);
 
   static UnrollBlock* fetch_unroll_info_helper(JavaThread* thread);
 
--- a/hotspot/src/share/vm/runtime/frame.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/frame.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -442,6 +442,14 @@
   char* description;
   int owner;
   int priority;
+
+  FrameValue() {
+    location = NULL;
+    description = NULL;
+    owner = -1;
+    priority = 0;
+  }
+
 };
 
 
--- a/hotspot/src/share/vm/runtime/globals.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/globals.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -306,35 +306,36 @@
   _flags = Flags(_flags & ~KIND_DIAGNOSTIC);
 }
 
-// Get custom message for this locked flag, or return NULL if
-// none is available.
-void Flag::get_locked_message(char* buf, int buflen) const {
+// Get custom message for this locked flag, or NULL if
+// none is available. Returns message type produced.
+Flag::MsgType Flag::get_locked_message(char* buf, int buflen) const {
   buf[0] = '\0';
   if (is_diagnostic() && !is_unlocked()) {
     jio_snprintf(buf, buflen,
                  "Error: VM option '%s' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.\n"
                  "Error: The unlock option must precede '%s'.\n",
                  _name, _name);
-    return;
+    return Flag::DIAGNOSTIC_FLAG_BUT_LOCKED;
   }
   if (is_experimental() && !is_unlocked()) {
     jio_snprintf(buf, buflen,
                  "Error: VM option '%s' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.\n"
                  "Error: The unlock option must precede '%s'.\n",
                  _name, _name);
-    return;
+    return Flag::EXPERIMENTAL_FLAG_BUT_LOCKED;
   }
   if (is_develop() && is_product_build()) {
     jio_snprintf(buf, buflen, "Error: VM option '%s' is develop and is available only in debug version of VM.\n",
                  _name);
-    return;
+    return Flag::DEVELOPER_FLAG_BUT_PRODUCT_BUILD;
   }
   if (is_notproduct() && is_product_build()) {
     jio_snprintf(buf, buflen, "Error: VM option '%s' is notproduct and is available only in debug version of VM.\n",
                  _name);
-    return;
+    return Flag::NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD;
   }
   get_locked_message_ext(buf, buflen);
+  return Flag::NONE;
 }
 
 bool Flag::is_writeable() const {
@@ -348,11 +349,6 @@
   return is_manageable() || is_external_ext();
 }
 
-
-// Length of format string (e.g. "%.1234s") for printing ccstr below
-#define FORMAT_BUFFER_LEN 16
-
-PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
 void Flag::print_on(outputStream* st, bool withComments, bool printRanges) {
   // Don't print notproduct and develop flags in a product build.
   if (is_constant_in_binary()) {
@@ -384,14 +380,8 @@
       if (cp != NULL) {
         const char* eol;
         while ((eol = strchr(cp, '\n')) != NULL) {
-          char format_buffer[FORMAT_BUFFER_LEN];
           size_t llen = pointer_delta(eol, cp, sizeof(char));
-          jio_snprintf(format_buffer, FORMAT_BUFFER_LEN,
-                       "%%." SIZE_FORMAT "s", llen);
-          PRAGMA_DIAG_PUSH
-          PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-          st->print(format_buffer, cp);
-          PRAGMA_DIAG_POP
+          st->print("%.*s", (int)llen, cp);
           st->cr();
           cp = eol+1;
           st->print("%5s %-35s += ", "", _name);
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -282,6 +282,14 @@
     ERR_OTHER
   };
 
+  enum MsgType {
+    NONE = 0,
+    DIAGNOSTIC_FLAG_BUT_LOCKED,
+    EXPERIMENTAL_FLAG_BUT_LOCKED,
+    DEVELOPER_FLAG_BUT_PRODUCT_BUILD,
+    NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD
+  };
+
   const char* _type;
   const char* _name;
   void* _addr;
@@ -367,7 +375,7 @@
 
   void unlock_diagnostic();
 
-  void get_locked_message(char*, int) const;
+  Flag::MsgType get_locked_message(char*, int) const;
   void get_locked_message_ext(char*, int) const;
 
   // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
@@ -804,7 +812,7 @@
           "Inline Thread.currentThread, etc")                               \
                                                                             \
   develop(bool, InlineUnsafeOps, true,                                      \
-          "Inline memory ops (native methods) from sun.misc.Unsafe")        \
+          "Inline memory ops (native methods) from Unsafe")                 \
                                                                             \
   product(bool, CriticalJNINatives, true,                                   \
           "Check for critical JNI entry points")                            \
@@ -1622,12 +1630,6 @@
           "Number of times to retry allocations when "                      \
           "blocked by the GC locker")                                       \
                                                                             \
-  develop(bool, UseCMSAdaptiveFreeLists, true,                              \
-          "Use adaptive free lists in the CMS generation")                  \
-                                                                            \
-  develop(bool, UseAsyncConcMarkSweepGC, true,                              \
-          "Use Asynchronous Concurrent Mark-Sweep GC in the old generation")\
-                                                                            \
   product(bool, UseCMSBestFit, true,                                        \
           "Use CMS best fit allocation strategy")                           \
                                                                             \
@@ -1822,10 +1824,6 @@
           "When CMS class unloading is enabled, the maximum CMS cycle "     \
           "count for which classes may not be unloaded")                    \
                                                                             \
-  develop(intx, CMSDictionaryChoice, 0,                                     \
-          "Use BinaryTreeDictionary as default in the CMS generation")      \
-          range(0, 2)                                                       \
-                                                                            \
   product(uintx, CMSIndexedFreeListReplenish, 4,                            \
           "Replenish an indexed free list with this number of chunks")      \
           range(1, max_uintx)                                               \
@@ -1840,9 +1838,6 @@
   product(bool, CMSLoopWarn, false,                                         \
           "Warn in case of excessive CMS looping")                          \
                                                                             \
-  develop(bool, CMSOverflowEarlyRestoration, false,                         \
-          "Restore preserved marks early")                                  \
-                                                                            \
   /* where does the range max value of (max_jint - 1) come from? */         \
   product(size_t, MarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M),         \
           "Maximum size of marking stack")                                  \
@@ -2080,10 +2075,6 @@
           "unloading of classes when class unloading is enabled")           \
           range(0, 100)                                                     \
                                                                             \
-  develop(bool, CMSTestInFreeList, false,                                   \
-          "Check if the coalesced range is already in the "                 \
-          "free lists as claimed")                                          \
-                                                                            \
   notproduct(bool, CMSVerifyReturnedBytes, false,                           \
           "Check that all the garbage collected was returned to the "       \
           "free lists")                                                     \
@@ -2889,6 +2880,9 @@
   product(bool, AggressiveOpts, false,                                      \
           "Enable aggressive optimizations - see arguments.cpp")            \
                                                                             \
+  product_pd(bool, CompactStrings,                                          \
+          "Enable Strings to use single byte chars in backing store")       \
+                                                                            \
   product_pd(uintx, TypeProfileLevel,                                       \
           "=XYZ, with Z: Type profiling of arguments at call; "             \
                      "Y: Type profiling of return value at call; "          \
@@ -4253,7 +4247,7 @@
           "Use locked-tracing when doing event-based tracing")              \
                                                                             \
   diagnostic(bool, UseUnalignedAccesses, false,                             \
-          "Use unaligned memory accesses in sun.misc.Unsafe")               \
+          "Use unaligned memory accesses in Unsafe")                        \
                                                                             \
   product_pd(bool, PreserveFramePointer,                                    \
              "Use the FP register for holding the frame pointer "           \
--- a/hotspot/src/share/vm/runtime/handles.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/handles.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -212,7 +212,8 @@
 }
 
 bool instanceKlassHandle::is_instanceKlass(const Klass* k) {
-  return k->oop_is_instance();
+  // Need this to avoid circular include dependency
+  return k->is_instance_klass();
 }
 
 #endif
--- a/hotspot/src/share/vm/runtime/java.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/java.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -575,6 +575,11 @@
 void vm_abort(bool dump_core) {
   vm_perform_shutdown_actions();
   os::wait_for_keypress_at_exit();
+
+  // Flush stdout and stderr before abort.
+  fflush(stdout);
+  fflush(stderr);
+
   os::abort(dump_core);
   ShouldNotReachHere();
 }
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -289,21 +289,20 @@
 // Implementation of JavaCalls (low level)
 
 
-void JavaCalls::call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS) {
+void JavaCalls::call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) {
   // Check if we need to wrap a potential OS exception handler around thread
   // This is used for e.g. Win32 structured exception handlers
   assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls");
   // Need to wrap each and every time, since there might be native code down the
   // stack that has installed its own exception handlers
-  os::os_exception_wrapper(call_helper, result, &method, args, THREAD);
+  os::os_exception_wrapper(call_helper, result, method, args, THREAD);
 }
 
-void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) {
+void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS) {
   // During dumping, Java execution environment is not fully initialized. Also, Java execution
   // may cause undesirable side-effects in the class metadata.
   assert(!DumpSharedSpaces, "must not execute Java bytecodes when dumping");
 
-  methodHandle method = *m;
   JavaThread* thread = (JavaThread*)THREAD;
   assert(thread->is_Java_thread(), "must be called by a java thread");
   assert(method.not_null(), "must have a method to call");
@@ -546,7 +545,7 @@
 };
 
 
-void JavaCallArguments::verify(methodHandle method, BasicType return_type,
+void JavaCallArguments::verify(const methodHandle& method, BasicType return_type,
   Thread *thread) {
   guarantee(method->size_of_parameters() == size_of_parameters(), "wrong no. of arguments pushed");
 
--- a/hotspot/src/share/vm/runtime/javaCalls.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/javaCalls.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -189,7 +189,7 @@
   int   size_of_parameters() const { return _size; }
 
   // Verify that pushed arguments fits a given method
-  void verify(methodHandle method, BasicType return_type, Thread *thread);
+  void verify(const methodHandle& method, BasicType return_type, Thread *thread);
 };
 
 // All calls to Java have to go via JavaCalls. Sets up the stack frame
@@ -197,7 +197,7 @@
 //
 
 class JavaCalls: AllStatic {
-  static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS);
+  static void call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS);
  public:
   // call_special
   // ------------
@@ -227,7 +227,7 @@
   static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 
   // Low-level interface
-  static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS);
+  static void call(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS);
 };
 
 #endif // SHARE_VM_RUNTIME_JAVACALLS_HPP
--- a/hotspot/src/share/vm/runtime/os.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -96,8 +96,7 @@
   // Output will be of the form "YYYY-MM-DDThh:mm:ss.mmm+zzzz\0"
   //                                      1         2
   //                             12345678901234567890123456789
-  static const char* iso8601_format =
-    "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d";
+  // format string: "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d"
   static const size_t needed_buffer = 29;
 
   // Sanity check the arguments
@@ -158,7 +157,8 @@
   // Print an ISO 8601 date and time stamp into the buffer
   const int year = 1900 + time_struct.tm_year;
   const int month = 1 + time_struct.tm_mon;
-  const int printed = jio_snprintf(buffer, buffer_length, iso8601_format,
+  const int printed = jio_snprintf(buffer, buffer_length,
+                                   "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d",
                                    year,
                                    month,
                                    time_struct.tm_mday,
@@ -1394,7 +1394,7 @@
 // Returns true if the current stack pointer is above the stack shadow
 // pages, false otherwise.
 
-bool os::stack_shadow_pages_available(Thread *thread, methodHandle method) {
+bool os::stack_shadow_pages_available(Thread *thread, const methodHandle& method) {
   assert(StackRedPages > 0 && StackYellowPages > 0,"Sanity check");
   address sp = current_stack_pointer();
   // Check if we have StackShadowPages above the yellow zone.  This parameter
--- a/hotspot/src/share/vm/runtime/os.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/os.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -96,7 +96,7 @@
 const bool ExecMem = true;
 
 // Typedef for structured exception handling support
-typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
+typedef void (*java_call_t)(JavaValue* value, const methodHandle& method, JavaCallArguments* args, Thread* thread);
 
 class MallocTracker;
 
@@ -263,7 +263,7 @@
   static bool uses_stack_guard_pages();
   static bool allocate_stack_guard_pages();
   static void bang_stack_shadow_pages();
-  static bool stack_shadow_pages_available(Thread *thread, methodHandle method);
+  static bool stack_shadow_pages_available(Thread *thread, const methodHandle& method);
 
   // OS interface to Virtual Memory
 
@@ -722,7 +722,7 @@
   static void init_random(long initval);   // initialize random sequence
 
   // Structured OS Exception support
-  static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
+  static void os_exception_wrapper(java_call_t f, JavaValue* value, const methodHandle& method, JavaCallArguments* args, Thread* thread);
 
   // On Posix compatible OS it will simply check core dump limits while on Windows
   // it will check if dump file can be created. Check or prepare a core dump to be
--- a/hotspot/src/share/vm/runtime/park.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/park.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -121,22 +121,13 @@
 
     // Current association
     Thread * AssociatedWith ;
-    intptr_t RawThreadIdentity ;        // LWPID etc
-    volatile int Incarnation ;
-
-    // diagnostic : keep track of last thread to wake this thread.
-    // this is useful for construction of dependency graphs.
-    void * LastWaker ;
 
   public:
     // MCS-CLH list linkage and Native Mutex/Monitor
     ParkEvent * volatile ListNext ;
-    ParkEvent * volatile ListPrev ;
     volatile intptr_t OnList ;
     volatile int TState ;
     volatile int Notified ;             // for native monitor construct
-    volatile int IsWaiting ;            // Enqueued on WaitSet
-
 
   private:
     static ParkEvent * volatile FreeList ;
@@ -155,11 +146,9 @@
        AssociatedWith = NULL ;
        FreeNext       = NULL ;
        ListNext       = NULL ;
-       ListPrev       = NULL ;
        OnList         = 0 ;
        TState         = 0 ;
        Notified       = 0 ;
-       IsWaiting      = 0 ;
     }
 
     // We use placement-new to force ParkEvent instances to be
--- a/hotspot/src/share/vm/runtime/reflection.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/reflection.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -330,7 +330,7 @@
     return TypeArrayKlass::cast(tak)->allocate(length, THREAD);
   } else {
     Klass* k = java_lang_Class::as_Klass(element_mirror);
-    if (k->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
+    if (k->is_array_klass() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
       THROW_0(vmSymbols::java_lang_IllegalArgumentException());
     }
     return oopFactory::new_objArray(k, length, THREAD);
@@ -366,7 +366,7 @@
     klass = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
   } else {
     klass = java_lang_Class::as_Klass(element_mirror);
-    if (klass->oop_is_array()) {
+    if (klass->is_array_klass()) {
       int k_dim = ArrayKlass::cast(klass)->dimension();
       if (k_dim + len > MAX_DIM) {
         THROW_0(vmSymbols::java_lang_IllegalArgumentException());
@@ -387,7 +387,7 @@
   }
 
   Klass* klass = java_lang_Class::as_Klass(mirror);
-  if (!klass->oop_is_array()) {
+  if (!klass->is_array_klass()) {
     return NULL;
   }
 
@@ -395,14 +395,14 @@
 #ifdef ASSERT
   oop result2 = NULL;
   if (ArrayKlass::cast(klass)->dimension() == 1) {
-    if (klass->oop_is_typeArray()) {
+    if (klass->is_typeArray_klass()) {
       result2 = basic_type_arrayklass_to_mirror(klass, CHECK_NULL);
     } else {
       result2 = ObjArrayKlass::cast(klass)->element_klass()->java_mirror();
     }
   } else {
     Klass* lower_dim = ArrayKlass::cast(klass)->lower_dimension();
-    assert(lower_dim->oop_is_array(), "just checking");
+    assert(lower_dim->is_array_klass(), "just checking");
     result2 = lower_dim->java_mirror();
   }
   assert(result == result2, "results must be consistent");
@@ -495,7 +495,7 @@
   }
 
   Klass* host_class = current_class;
-  while (host_class->oop_is_instance() &&
+  while (host_class->is_instance_klass() &&
          InstanceKlass::cast(host_class)->is_anonymous()) {
     Klass* next_host_class = InstanceKlass::cast(host_class)->host_klass();
     if (next_host_class == NULL)  break;
@@ -612,7 +612,7 @@
 }
 
 
-objArrayHandle Reflection::get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS) {
+objArrayHandle Reflection::get_parameter_types(const methodHandle& method, int parameter_count, oop* return_type, TRAPS) {
   // Allocate array holding parameter types (java.lang.Class instances)
   objArrayOop m = oopFactory::new_objArray(SystemDictionary::Class_klass(), parameter_count, CHECK_(objArrayHandle()));
   objArrayHandle mirrors (THREAD, m);
@@ -635,7 +635,7 @@
   return mirrors;
 }
 
-objArrayHandle Reflection::get_exception_types(methodHandle method, TRAPS) {
+objArrayHandle Reflection::get_exception_types(const methodHandle& method, TRAPS) {
   return method->resolved_checked_exceptions(THREAD);
 }
 
@@ -647,11 +647,9 @@
     return Handle(THREAD, Universe::java_mirror(type));
   }
 
-  oop loader = InstanceKlass::cast(k())->class_loader();
-  oop protection_domain = k()->protection_domain();
   Klass* result = SystemDictionary::resolve_or_fail(signature,
-                                    Handle(THREAD, loader),
-                                    Handle(THREAD, protection_domain),
+                                    Handle(THREAD, k->class_loader()),
+                                    Handle(THREAD, k->protection_domain()),
                                     true, CHECK_(Handle()));
 
   if (TraceClassResolution) {
@@ -663,7 +661,7 @@
 }
 
 
-oop Reflection::new_method(methodHandle method, bool for_constant_pool_access, TRAPS) {
+oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_access, TRAPS) {
   // Allow sun.reflect.ConstantPool to refer to <clinit> methods as java.lang.reflect.Methods.
   assert(!method()->is_initializer() ||
          (for_constant_pool_access && method()->is_static()),
@@ -726,7 +724,7 @@
 }
 
 
-oop Reflection::new_constructor(methodHandle method, TRAPS) {
+oop Reflection::new_constructor(const methodHandle& method, TRAPS) {
   assert(method()->is_initializer(), "should call new_method instead");
 
   instanceKlassHandle  holder (THREAD, method->method_holder());
@@ -824,7 +822,7 @@
 }
 
 
-methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method,
+methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, const methodHandle& method,
                                                 KlassHandle recv_klass, Handle receiver, TRAPS) {
   assert(!method.is_null() , "method should not be null");
 
@@ -839,7 +837,7 @@
 }
 
 
-oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method,
+oop Reflection::invoke(instanceKlassHandle klass, const methodHandle& reflected_method,
                        Handle receiver, bool override, objArrayHandle ptypes,
                        BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS) {
   ResourceMark rm(THREAD);
--- a/hotspot/src/share/vm/runtime/reflection.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/reflection.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,8 +48,8 @@
   static Klass* basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS);
   static oop      basic_type_arrayklass_to_mirror(Klass* basic_type_arrayklass, TRAPS);
 
-  static objArrayHandle get_parameter_types(methodHandle method, int parameter_count, oop* return_type, TRAPS);
-  static objArrayHandle get_exception_types(methodHandle method, TRAPS);
+  static objArrayHandle get_parameter_types(const methodHandle& method, int parameter_count, oop* return_type, TRAPS);
+  static objArrayHandle get_exception_types(const methodHandle& method, TRAPS);
   // Creating new java.lang.reflect.xxx wrappers
   static Handle new_type(Symbol* signature, KlassHandle k, TRAPS);
 
@@ -110,9 +110,9 @@
   //
 
   // Create a java.lang.reflect.Method object based on a method
-  static oop new_method(methodHandle method, bool for_constant_pool_access, TRAPS);
+  static oop new_method(const methodHandle& method, bool for_constant_pool_access, TRAPS);
   // Create a java.lang.reflect.Constructor object based on a method
-  static oop new_constructor(methodHandle method, TRAPS);
+  static oop new_constructor(const methodHandle& method, TRAPS);
   // Create a java.lang.reflect.Field object based on a field descriptor
   static oop new_field(fieldDescriptor* fd, TRAPS);
   // Create a java.lang.reflect.Parameter object based on a
@@ -122,9 +122,16 @@
 
 private:
   // method resolution for invoke
-  static methodHandle resolve_interface_call(instanceKlassHandle klass, methodHandle method, KlassHandle recv_klass, Handle receiver, TRAPS);
+  static methodHandle resolve_interface_call(instanceKlassHandle klass, const methodHandle& method, KlassHandle recv_klass, Handle receiver, TRAPS);
   // Method call (shared by invoke_method and invoke_constructor)
-  static oop  invoke(instanceKlassHandle klass, methodHandle method, Handle receiver, bool override, objArrayHandle ptypes, BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS);
+  static oop  invoke(instanceKlassHandle klass,
+                     const methodHandle& method,
+                     Handle receiver,
+                     bool override,
+                     objArrayHandle ptypes,
+                     BasicType rtype,
+                     objArrayHandle args,
+                     bool is_method_invoke, TRAPS);
 
   // Narrowing of basic types. Used to create correct jvalues for
   // boolean, byte, char and short return return values from interpreter
--- a/hotspot/src/share/vm/runtime/relocator.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/relocator.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -125,7 +125,7 @@
 //-----------------------------------------------------------------------------------------------------------
 // Relocator code
 
-Relocator::Relocator(methodHandle m, RelocatorListener* listener) {
+Relocator::Relocator(const methodHandle& m, RelocatorListener* listener) {
   set_method(m);
   set_code_length(method()->code_size());
   set_code_array(NULL);
--- a/hotspot/src/share/vm/runtime/relocator.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/relocator.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
 
 class Relocator : public ResourceObj {
  public:
-  Relocator(methodHandle method, RelocatorListener* listener);
+  Relocator(const methodHandle& method, RelocatorListener* listener);
   methodHandle insert_space_at(int bci, int space, u_char inst_buffer[], TRAPS);
 
   // Callbacks from ChangeItem's
@@ -81,7 +81,7 @@
   void set_compressed_line_number_table_size(int size)        { _compressed_line_number_table_size = size; }
 
   methodHandle method() const               { return _method; }
-  void set_method(methodHandle method)      { _method = method; }
+  void set_method(const methodHandle& method)      { _method = method; }
 
   // This will return a raw bytecode, which is possibly rewritten.
   Bytecodes::Code code_at(int bci) const          { return (Bytecodes::Code) code_array()[bci]; }
--- a/hotspot/src/share/vm/runtime/safepoint.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -122,7 +122,7 @@
 
   // Save the starting time, so that it can be compared to see if this has taken
   // too long to complete.
-  jlong safepoint_limit_time;
+  jlong safepoint_limit_time = 0;
   timeout_error_printed = false;
 
   // PrintSafepointStatisticsTimeout can be specified separately. When
@@ -901,7 +901,7 @@
 
 
 void ThreadSafepointState::print_on(outputStream *st) const {
-  const char *s;
+  const char *s = NULL;
 
   switch(_type) {
     case _running                : s = "_running";              break;
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1142,7 +1142,7 @@
            callee->is_method_handle_intrinsic() ||
            callee->is_compiled_lambda_form(),
            "actual receiver must be subclass of static receiver klass");
-    if (receiver_klass->oop_is_instance()) {
+    if (receiver_klass->is_instance_klass()) {
       if (InstanceKlass::cast(receiver_klass())->is_not_initialized()) {
         tty->print_cr("ERROR: Klass not yet initialized!!");
         receiver_klass()->print();
@@ -1697,7 +1697,7 @@
 }
 
 #ifdef ASSERT
-void SharedRuntime::check_member_name_argument_is_last_argument(methodHandle method,
+void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method,
                                                                 const BasicType* sig_bt,
                                                                 const VMRegPair* regs) {
   ResourceMark rm;
@@ -2430,7 +2430,7 @@
   return _adapters->new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
 }
 
-AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(methodHandle method) {
+AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& method) {
   // Use customized signature handler.  Need to lock around updates to
   // the AdapterHandlerTable (it is not safe for concurrent readers
   // and a single writer: this could be fixed if it becomes a
@@ -2640,7 +2640,7 @@
  * arguments, and transitions to native.  On return from the native we transition
  * back to java blocking if a safepoint is in progress.
  */
-void AdapterHandlerLibrary::create_native_wrapper(methodHandle method) {
+void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) {
   ResourceMark rm;
   nmethod* nm = NULL;
 
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -361,7 +361,7 @@
   // return value is the maximum number of VMReg stack slots the convention will use.
   static int java_calling_convention(const BasicType* sig_bt, VMRegPair* regs, int total_args_passed, int is_outgoing);
 
-  static void check_member_name_argument_is_last_argument(methodHandle method,
+  static void check_member_name_argument_is_last_argument(const methodHandle& method,
                                                           const BasicType* sig_bt,
                                                           const VMRegPair* regs) NOT_DEBUG_RETURN;
 
@@ -472,7 +472,7 @@
   // is a JNI critical method, or a compiled method handle adapter,
   // such as _invokeBasic, _linkToVirtual, etc.
   static nmethod* generate_native_wrapper(MacroAssembler* masm,
-                                          methodHandle method,
+                                          const methodHandle& method,
                                           int compile_id,
                                           BasicType* sig_bt,
                                           VMRegPair* regs,
@@ -680,8 +680,8 @@
 
   static AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint,
                                         address i2c_entry, address c2i_entry, address c2i_unverified_entry);
-  static void create_native_wrapper(methodHandle method);
-  static AdapterHandlerEntry* get_adapter(methodHandle method);
+  static void create_native_wrapper(const methodHandle& method);
+  static AdapterHandlerEntry* get_adapter(const methodHandle& method);
 
   static void print_handler(const CodeBlob* b) { print_handler_on(tty, b); }
   static void print_handler_on(outputStream* st, const CodeBlob* b);
--- a/hotspot/src/share/vm/runtime/signature.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/signature.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -242,7 +242,7 @@
 
   void do_void()    { ShouldNotReachHere(); }
 
-  Fingerprinter(methodHandle method) : SignatureIterator(method->signature()) {
+  Fingerprinter(const methodHandle& method) : SignatureIterator(method->signature()) {
     mh = method;
     _fingerprint = 0;
   }
@@ -320,7 +320,7 @@
   virtual void pass_double()           { pass_long(); }  // may be same as long
 #endif
 
-  NativeSignatureIterator(methodHandle method) : SignatureIterator(method->signature()) {
+  NativeSignatureIterator(const methodHandle& method) : SignatureIterator(method->signature()) {
     _method = method;
     _offset = 0;
     _jni_offset = 0;
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -185,7 +185,7 @@
   }
 }
 
-nmethod* SimpleThresholdPolicy::event(methodHandle method, methodHandle inlinee,
+nmethod* SimpleThresholdPolicy::event(const methodHandle& method, const methodHandle& inlinee,
                                       int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) {
   if (comp_level == CompLevel_none &&
       JvmtiExport::can_post_interpreter_events() &&
@@ -222,7 +222,7 @@
 }
 
 // Check if the method can be compiled, change level if necessary
-void SimpleThresholdPolicy::compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) {
+void SimpleThresholdPolicy::compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) {
   assert(level <= TieredStopAtLevel, "Invalid compilation level");
   if (level == CompLevel_none) {
     return;
@@ -249,7 +249,7 @@
 }
 
 // Tell the broker to compile the method
-void SimpleThresholdPolicy::submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread) {
+void SimpleThresholdPolicy::submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) {
   int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count();
   CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", thread);
 }
@@ -377,7 +377,7 @@
 
 
 // Handle the invocation event.
-void SimpleThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh,
+void SimpleThresholdPolicy::method_invocation_event(const methodHandle& mh, const methodHandle& imh,
                                               CompLevel level, nmethod* nm, JavaThread* thread) {
   if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) {
     CompLevel next_level = call_event(mh(), level);
@@ -389,7 +389,7 @@
 
 // Handle the back branch event. Notice that we can compile the method
 // with a regular entry from here.
-void SimpleThresholdPolicy::method_back_branch_event(methodHandle mh, methodHandle imh,
+void SimpleThresholdPolicy::method_back_branch_event(const methodHandle& mh, const methodHandle& imh,
                                                      int bci, CompLevel level, nmethod* nm, JavaThread* thread) {
   // If the method is already compiling, quickly bail out.
   if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) {
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,9 +67,9 @@
   // Print policy-specific information if necessary
   virtual void print_specific(EventType type, methodHandle mh, methodHandle imh, int bci, CompLevel level) { }
   // Check if the method can be compiled, change level if necessary
-  void compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread);
+  void compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread);
   // Submit a given method for compilation
-  virtual void submit_compile(methodHandle mh, int bci, CompLevel level, JavaThread* thread);
+  virtual void submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread);
   // Simple methods are as good being compiled with C1 as C2.
   // This function tells if it's such a function.
   inline bool is_trivial(Method* method);
@@ -87,9 +87,9 @@
     }
     return CompLevel_none;
   }
-  virtual void method_invocation_event(methodHandle method, methodHandle inlinee,
+  virtual void method_invocation_event(const methodHandle& method, const methodHandle& inlinee,
                                        CompLevel level, nmethod* nm, JavaThread* thread);
-  virtual void method_back_branch_event(methodHandle method, methodHandle inlinee,
+  virtual void method_back_branch_event(const methodHandle& method, const methodHandle& inlinee,
                                         int bci, CompLevel level, nmethod* nm, JavaThread* thread);
 public:
   SimpleThresholdPolicy() : _c1_count(0), _c2_count(0) { }
@@ -103,7 +103,7 @@
   virtual void delay_compilation(Method* method) { }
   virtual void disable_compilation(Method* method) { }
   virtual void reprofile(ScopeDesc* trap_scope, bool is_osr);
-  virtual nmethod* event(methodHandle method, methodHandle inlinee,
+  virtual nmethod* event(const methodHandle& method, const methodHandle& inlinee,
                          int branch_bci, int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread);
   // Select task is called by CompileBroker. We should return a task or NULL.
   virtual CompileTask* select_task(CompileQueue* compile_queue);
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -68,6 +68,14 @@
       method->is_constant_getter()) {
     return true;
   }
+#if INCLUDE_JVMCI
+  if (UseJVMCICompiler) {
+    if (TieredCompilation && CompileBroker::compiler(CompLevel_full_optimization) != NULL &&
+        CompileBroker::compiler(CompLevel_full_optimization)->is_trivial(method)) {
+      return true;
+    }
+  }
+#endif
   if (method->has_loops() || method->code_size() >= 15) {
     return false;
   }
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -116,7 +116,7 @@
 // global list of blocks of monitors
 // gBlockList is really PaddedEnd<ObjectMonitor> *, but we don't
 // want to expose the PaddedEnd template more than necessary.
-ObjectMonitor * ObjectSynchronizer::gBlockList = NULL;
+ObjectMonitor * volatile ObjectSynchronizer::gBlockList = NULL;
 // global monitor free list
 ObjectMonitor * volatile ObjectSynchronizer::gFreeList  = NULL;
 // global monitor in-use list, for moribund threads,
@@ -890,21 +890,22 @@
 
   return NULL;
 }
+
 // Visitors ...
 
 void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) {
-  PaddedEnd<ObjectMonitor> * block = (PaddedEnd<ObjectMonitor> *)gBlockList;
-  ObjectMonitor* mid;
-  while (block) {
+  PaddedEnd<ObjectMonitor> * block =
+    (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
+  while (block != NULL) {
     assert(block->object() == CHAINMARKER, "must be a block header");
     for (int i = _BLOCKSIZE - 1; i > 0; i--) {
-      mid = (ObjectMonitor *)(block + i);
-      oop object = (oop) mid->object();
+      ObjectMonitor* mid = (ObjectMonitor *)(block + i);
+      oop object = (oop)mid->object();
       if (object != NULL) {
         closure->do_monitor(mid);
       }
     }
-    block = (PaddedEnd<ObjectMonitor> *) block->FreeNext;
+    block = (PaddedEnd<ObjectMonitor> *)block->FreeNext;
   }
 }
 
@@ -919,9 +920,9 @@
 
 void ObjectSynchronizer::oops_do(OopClosure* f) {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
-  for (PaddedEnd<ObjectMonitor> * block =
-       (PaddedEnd<ObjectMonitor> *)gBlockList; block != NULL;
-       block = (PaddedEnd<ObjectMonitor> *)next(block)) {
+  PaddedEnd<ObjectMonitor> * block =
+    (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
+  for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)next(block)) {
     assert(block->object() == CHAINMARKER, "must be a block header");
     for (int i = 1; i < _BLOCKSIZE; i++) {
       ObjectMonitor* mid = (ObjectMonitor *)&block[i];
@@ -1139,7 +1140,9 @@
     // The very first objectMonitor in a block is reserved and dedicated.
     // It serves as blocklist "next" linkage.
     temp[0].FreeNext = gBlockList;
-    gBlockList = temp;
+    // There are lock-free uses of gBlockList so make sure that
+    // the previous stores happen before we update gBlockList.
+    OrderAccess::release_store_ptr(&gBlockList, temp);
 
     // Add the new string of objectMonitors to the global free list
     temp[_BLOCKSIZE - 1].FreeNext = gFreeList;
@@ -1621,31 +1624,33 @@
       nInuse += gOmInUseCount;
     }
 
-  } else for (PaddedEnd<ObjectMonitor> * block =
-              (PaddedEnd<ObjectMonitor> *)gBlockList; block != NULL;
-              block = (PaddedEnd<ObjectMonitor> *)next(block)) {
-    // Iterate over all extant monitors - Scavenge all idle monitors.
-    assert(block->object() == CHAINMARKER, "must be a block header");
-    nInCirculation += _BLOCKSIZE;
-    for (int i = 1; i < _BLOCKSIZE; i++) {
-      ObjectMonitor* mid = (ObjectMonitor*)&block[i];
-      oop obj = (oop) mid->object();
+  } else {
+    PaddedEnd<ObjectMonitor> * block =
+      (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
+    for (; block != NULL; block = (PaddedEnd<ObjectMonitor> *)next(block)) {
+      // Iterate over all extant monitors - Scavenge all idle monitors.
+      assert(block->object() == CHAINMARKER, "must be a block header");
+      nInCirculation += _BLOCKSIZE;
+      for (int i = 1; i < _BLOCKSIZE; i++) {
+        ObjectMonitor* mid = (ObjectMonitor*)&block[i];
+        oop obj = (oop)mid->object();
 
-      if (obj == NULL) {
-        // The monitor is not associated with an object.
-        // The monitor should either be a thread-specific private
-        // free list or the global free list.
-        // obj == NULL IMPLIES mid->is_busy() == 0
-        guarantee(!mid->is_busy(), "invariant");
-        continue;
-      }
-      deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp);
+        if (obj == NULL) {
+          // The monitor is not associated with an object.
+          // The monitor should either be a thread-specific private
+          // free list or the global free list.
+          // obj == NULL IMPLIES mid->is_busy() == 0
+          guarantee(!mid->is_busy(), "invariant");
+          continue;
+        }
+        deflated = deflate_monitor(mid, obj, &freeHeadp, &freeTailp);
 
-      if (deflated) {
-        mid->FreeNext = NULL;
-        nScavenged++;
-      } else {
-        nInuse++;
+        if (deflated) {
+          mid->FreeNext = NULL;
+          nScavenged++;
+        } else {
+          nInuse++;
+        }
       }
     }
   }
@@ -1789,18 +1794,18 @@
 
 // Verify all monitors in the monitor cache, the verification is weak.
 void ObjectSynchronizer::verify() {
-  PaddedEnd<ObjectMonitor> * block = (PaddedEnd<ObjectMonitor> *)gBlockList;
-  ObjectMonitor* mid;
-  while (block) {
+  PaddedEnd<ObjectMonitor> * block =
+    (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
+  while (block != NULL) {
     assert(block->object() == CHAINMARKER, "must be a block header");
     for (int i = 1; i < _BLOCKSIZE; i++) {
-      mid = (ObjectMonitor *)(block + i);
-      oop object = (oop) mid->object();
+      ObjectMonitor* mid = (ObjectMonitor *)(block + i);
+      oop object = (oop)mid->object();
       if (object != NULL) {
         mid->verify();
       }
     }
-    block = (PaddedEnd<ObjectMonitor> *) block->FreeNext;
+    block = (PaddedEnd<ObjectMonitor> *)block->FreeNext;
   }
 }
 
@@ -1809,19 +1814,19 @@
 // the list of extant blocks without taking a lock.
 
 int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) {
-  PaddedEnd<ObjectMonitor> * block = (PaddedEnd<ObjectMonitor> *)gBlockList;
-
-  while (block) {
+  PaddedEnd<ObjectMonitor> * block =
+    (PaddedEnd<ObjectMonitor> *)OrderAccess::load_ptr_acquire(&gBlockList);
+  while (block != NULL) {
     assert(block->object() == CHAINMARKER, "must be a block header");
     if (monitor > (ObjectMonitor *)&block[0] &&
         monitor < (ObjectMonitor *)&block[_BLOCKSIZE]) {
-      address mon = (address) monitor;
-      address blk = (address) block;
+      address mon = (address)monitor;
+      address blk = (address)block;
       size_t diff = mon - blk;
-      assert((diff % sizeof(PaddedEnd<ObjectMonitor>)) == 0, "check");
+      assert((diff % sizeof(PaddedEnd<ObjectMonitor>)) == 0, "must be aligned");
       return 1;
     }
-    block = (PaddedEnd<ObjectMonitor> *) block->FreeNext;
+    block = (PaddedEnd<ObjectMonitor> *)block->FreeNext;
   }
   return 0;
 }
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -140,7 +140,7 @@
   // global list of blocks of monitors
   // gBlockList is really PaddedEnd<ObjectMonitor> *, but we don't
   // want to expose the PaddedEnd template more than necessary.
-  static ObjectMonitor * gBlockList;
+  static ObjectMonitor * volatile gBlockList;
   // global monitor free list
   static ObjectMonitor * volatile gFreeList;
   // global monitor in-use list, for moribund threads,
--- a/hotspot/src/share/vm/runtime/thread.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -2101,7 +2101,7 @@
           frame f = last_frame();
           tty->print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", p2i(f.pc()), p2i(f.sp()));
         }
-        tty->print_cr(" of type: %s", InstanceKlass::cast(_pending_async_exception->klass())->external_name());
+        tty->print_cr(" of type: %s", _pending_async_exception->klass()->external_name());
       }
       _pending_async_exception = NULL;
       clear_has_async_exception();
@@ -2219,10 +2219,10 @@
 
       if (TraceExceptions) {
         ResourceMark rm;
-        tty->print_cr("Pending Async. exception installed of type: %s", InstanceKlass::cast(_pending_async_exception->klass())->external_name());
+        tty->print_cr("Pending Async. exception installed of type: %s", _pending_async_exception->klass()->external_name());
       }
       // for AbortVMOnException flag
-      Exceptions::debug_check_abort(InstanceKlass::cast(_pending_async_exception->klass())->external_name());
+      Exceptions::debug_check_abort(_pending_async_exception->klass()->external_name());
     }
   }
 
@@ -2933,12 +2933,8 @@
   if (thread_obj != NULL) {
     oop thread_group = java_lang_Thread::threadGroup(thread_obj);
     if (thread_group != NULL) {
-      typeArrayOop name = java_lang_ThreadGroup::name(thread_group);
       // ThreadGroup.name can be null
-      if (name != NULL) {
-        const char* str = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length());
-        return str;
-      }
+      return java_lang_ThreadGroup::name(thread_group);
     }
   }
   return NULL;
@@ -2952,12 +2948,8 @@
     if (thread_group != NULL) {
       oop parent = java_lang_ThreadGroup::parent(thread_group);
       if (parent != NULL) {
-        typeArrayOop name = java_lang_ThreadGroup::name(parent);
         // ThreadGroup.name can be null
-        if (name != NULL) {
-          const char* str = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length());
-          return str;
-        }
+        return java_lang_ThreadGroup::name(parent);
       }
     }
   }
@@ -3304,6 +3296,9 @@
 
   initialize_class(vmSymbols::java_lang_String(), CHECK);
 
+  // Inject CompactStrings value after the static initializers for String ran.
+  java_lang_String::set_compact_strings(CompactStrings);
+
   // Initialize java_lang.System (needed before creating the thread)
   initialize_class(vmSymbols::java_lang_System(), CHECK);
   // The VM creates & returns objects of this class. Make sure it's initialized.
@@ -3630,6 +3625,7 @@
     if (jvmciCompiler != NULL) {
       JVMCIRuntime::save_compiler(jvmciCompiler);
     }
+    JVMCIRuntime::maybe_print_flags(CHECK_JNI_ERR);
   }
 #endif // INCLUDE_JVMCI
 
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -278,6 +278,7 @@
 
 #define VM_STRUCTS(nonstatic_field, \
                    static_field, \
+                   static_ptr_volatile_field, \
                    unchecked_nonstatic_field, \
                    volatile_nonstatic_field, \
                    nonproduct_nonstatic_field, \
@@ -681,42 +682,42 @@
      static_field(SystemDictionary,            _shared_dictionary,                            Dictionary*)                           \
      static_field(SystemDictionary,            _system_loader_lock_obj,                       oop)                                   \
      static_field(SystemDictionary,            _loader_constraints,                           LoaderConstraintTable*)                \
-     static_field(SystemDictionary,            WK_KLASS(Object_klass),                        Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(String_klass),                        Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Class_klass),                         Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Cloneable_klass),                     Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(ClassLoader_klass),                   Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Serializable_klass),                  Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(System_klass),                        Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Throwable_klass),                     Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(ThreadDeath_klass),                   Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Error_klass),                         Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Exception_klass),                     Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(RuntimeException_klass),              Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(ClassNotFoundException_klass),        Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(NoClassDefFoundError_klass),          Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(LinkageError_klass),                  Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(ClassCastException_klass),            Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(ArrayStoreException_klass),           Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(VirtualMachineError_klass),           Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(OutOfMemoryError_klass),              Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(StackOverflowError_klass),            Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(ProtectionDomain_klass),              Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(AccessControlContext_klass),          Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(SecureClassLoader_klass),             Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Reference_klass),                     Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(SoftReference_klass),                 Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(WeakReference_klass),                 Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(FinalReference_klass),                Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(PhantomReference_klass),              Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Cleaner_klass),                       Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Finalizer_klass),                     Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Thread_klass),                        Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(ThreadGroup_klass),                   Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(Properties_klass),                    Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(StringBuffer_klass),                  Klass*)                                \
-     static_field(SystemDictionary,            WK_KLASS(MethodHandle_klass),                  Klass*)                                \
-     static_field(SystemDictionary,            _box_klasses[0],                               Klass*)                                \
+     static_field(SystemDictionary,            WK_KLASS(Object_klass),                        InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(String_klass),                        InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Class_klass),                         InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Cloneable_klass),                     InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(ClassLoader_klass),                   InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Serializable_klass),                  InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(System_klass),                        InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Throwable_klass),                     InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(ThreadDeath_klass),                   InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Error_klass),                         InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Exception_klass),                     InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(RuntimeException_klass),              InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(ClassNotFoundException_klass),        InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(NoClassDefFoundError_klass),          InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(LinkageError_klass),                  InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(ClassCastException_klass),            InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(ArrayStoreException_klass),           InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(VirtualMachineError_klass),           InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(OutOfMemoryError_klass),              InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(StackOverflowError_klass),            InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(ProtectionDomain_klass),              InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(AccessControlContext_klass),          InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(SecureClassLoader_klass),             InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Reference_klass),                     InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(SoftReference_klass),                 InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(WeakReference_klass),                 InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(FinalReference_klass),                InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(PhantomReference_klass),              InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Cleaner_klass),                       InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Finalizer_klass),                     InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Thread_klass),                        InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(ThreadGroup_klass),                   InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(Properties_klass),                    InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(StringBuffer_klass),                  InstanceKlass*)                        \
+     static_field(SystemDictionary,            WK_KLASS(MethodHandle_klass),                  InstanceKlass*)                        \
+     static_field(SystemDictionary,            _box_klasses[0],                               InstanceKlass*)                        \
      static_field(SystemDictionary,            _java_system_loader,                           oop)                                   \
                                                                                                                                      \
   /*************/                                                                                                                    \
@@ -1178,7 +1179,7 @@
   volatile_nonstatic_field(BasicLock,          _displaced_header,                             markOop)                               \
   nonstatic_field(BasicObjectLock,             _lock,                                         BasicLock)                             \
   nonstatic_field(BasicObjectLock,             _obj,                                          oop)                                   \
-     static_field(ObjectSynchronizer,          gBlockList,                                    ObjectMonitor*)                        \
+  static_ptr_volatile_field(ObjectSynchronizer, gBlockList,                                   ObjectMonitor*)                        \
                                                                                                                                      \
   /*********************/                                                                                                            \
   /* Matcher (C2 only) */                                                                                                            \
@@ -2897,6 +2898,11 @@
 #define GENERATE_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)                 \
  { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, &typeName::fieldName },
 
+// This macro generates a VMStructEntry line for a static pointer volatile field,
+// e.g.: "static ObjectMonitor * volatile gBlockList;"
+#define GENERATE_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type)    \
+ { QUOTE(typeName), QUOTE(fieldName), QUOTE(type), 1, 0, (void *)&typeName::fieldName },
+
 // This macro generates a VMStructEntry line for an unchecked
 // nonstatic field, in which the size of the type is also specified.
 // The type string is given as NULL, indicating an "opaque" type.
@@ -2922,10 +2928,15 @@
 #define CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)        \
  {typedef type dummyvtype; typeName *dummyObj = NULL; volatile dummyvtype* dummy = &dummyObj->fieldName; }
 
-// This macro checks the type of a VMStructEntry by comparing pointer types
+// This macro checks the type of a static VMStructEntry by comparing pointer types
 #define CHECK_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type)                    \
  {type* dummy = &typeName::fieldName; }
 
+// This macro checks the type of a static pointer volatile VMStructEntry by comparing pointer types,
+// e.g.: "static ObjectMonitor * volatile gBlockList;"
+#define CHECK_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY(typeName, fieldName, type)       \
+ {type volatile * dummy = &typeName::fieldName; }
+
 // This macro ensures the type of a field and its containing type are
 // present in the type table. The assertion string is shorter than
 // preferable because (incredibly) of a bug in Solstice NFS client
@@ -3136,6 +3147,7 @@
 
   VM_STRUCTS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
              GENERATE_STATIC_VM_STRUCT_ENTRY,
+             GENERATE_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY,
              GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY,
              GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
              GENERATE_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY,
@@ -3365,6 +3377,7 @@
 VMStructs::init() {
   VM_STRUCTS(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
              CHECK_STATIC_VM_STRUCT_ENTRY,
+             CHECK_STATIC_PTR_VOLATILE_VM_STRUCT_ENTRY,
              CHECK_NO_OP,
              CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY,
              CHECK_NONPRODUCT_NONSTATIC_VM_STRUCT_ENTRY,
@@ -3486,9 +3499,11 @@
                         CHECK_NO_OP,
                         CHECK_NO_OP,
                         CHECK_NO_OP,
+                        CHECK_NO_OP,
                         CHECK_NO_OP));
   debug_only(VM_STRUCTS(CHECK_NO_OP,
                         ENSURE_FIELD_TYPE_PRESENT,
+                        ENSURE_FIELD_TYPE_PRESENT,
                         CHECK_NO_OP,
                         ENSURE_FIELD_TYPE_PRESENT,
                         ENSURE_NONPRODUCT_FIELD_TYPE_PRESENT,
--- a/hotspot/src/share/vm/services/classLoadingService.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/services/classLoadingService.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -164,7 +164,7 @@
 
   class_size += k->size();
 
-  if (k->oop_is_instance()) {
+  if (k->is_instance_klass()) {
     class_size += k->methods()->size();
     // FIXME: Need to count the contents of methods
     class_size += k->constants()->size();
--- a/hotspot/src/share/vm/services/heapDumper.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/services/heapDumper.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -722,7 +722,7 @@
         o = oopDesc::load_decode_heap_oop((oop*)addr);
       }
 
-      // reflection and sun.misc.Unsafe classes may have a reference to a
+      // reflection and Unsafe classes may have a reference to a
       // Klass* so filter it out.
       assert(o->is_oop_or_null(), "Expected an oop or NULL at " PTR_FORMAT, p2i(o));
       writer->write_objectID(o);
@@ -895,9 +895,7 @@
 // creates HPROF_GC_CLASS_DUMP record for the given class and each of
 // its array classes
 void DumperSupport::dump_class_and_array_classes(DumpWriter* writer, Klass* k) {
-  Klass* klass = k;
-  assert(klass->oop_is_instance(), "not an InstanceKlass");
-  InstanceKlass* ik = (InstanceKlass*)klass;
+  InstanceKlass* ik = InstanceKlass::cast(k);
 
   // Ignore the class if it hasn't been initialized yet
   if (!ik->is_linked()) {
@@ -939,10 +937,10 @@
   dump_instance_field_descriptors(writer, k);
 
   // array classes
-  k = klass->array_klass_or_null();
+  k = k->array_klass_or_null();
   while (k != NULL) {
     Klass* klass = k;
-    assert(klass->oop_is_objArray(), "not an ObjArrayKlass");
+    assert(klass->is_objArray_klass(), "not an ObjArrayKlass");
 
     writer->write_u1(HPROF_GC_CLASS_DUMP);
     writer->write_classID(klass);
@@ -1126,7 +1124,7 @@
   writer->write_symbolID(m->name());                // method's name
   writer->write_symbolID(m->signature());           // method's signature
 
-  assert(m->method_holder()->oop_is_instance(), "not InstanceKlass");
+  assert(m->method_holder()->is_instance_klass(), "not InstanceKlass");
   writer->write_symbolID(m->method_holder()->source_file_name());  // source file name
   writer->write_u4(class_serial_num);               // class serial number
   writer->write_u4((u4) line_number);               // line number
@@ -1248,7 +1246,7 @@
     _writer = writer;
   }
   void do_klass(Klass* k) {
-    if (k->oop_is_instance()) {
+    if (k->is_instance_klass()) {
       InstanceKlass* ik = InstanceKlass::cast(k);
         writer()->write_u1(HPROF_GC_ROOT_STICKY_CLASS);
         writer()->write_classID(ik);
@@ -1396,7 +1394,7 @@
     if (oome) {
       assert(!Thread::current()->is_VM_thread(), "Dump from OutOfMemoryError cannot be called by the VMThread");
       // get OutOfMemoryError zero-parameter constructor
-      InstanceKlass* oome_ik = InstanceKlass::cast(SystemDictionary::OutOfMemoryError_klass());
+      InstanceKlass* oome_ik = SystemDictionary::OutOfMemoryError_klass();
       _oome_constructor = oome_ik->find_method(vmSymbols::object_initializer_name(),
                                                           vmSymbols::void_method_signature());
       // get thread throwing OOME when generating the heap dump at OOME
@@ -1553,7 +1551,7 @@
 
 // writes a HPROF_GC_CLASS_DUMP record for the given class
 void VM_HeapDumper::do_class_dump(Klass* k) {
-  if (k->oop_is_instance()) {
+  if (k->is_instance_klass()) {
     DumperSupport::dump_class_and_array_classes(writer(), k);
   }
 }
@@ -1850,7 +1848,6 @@
 }
 
 // dump the heap to given path.
-PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
 int HeapDumper::dump(const char* path) {
   assert(path != NULL && strlen(path) > 0, "path missing");
 
@@ -1888,13 +1885,8 @@
   if (print_to_tty()) {
     timer()->stop();
     if (error() == NULL) {
-      char msg[256];
-      sprintf(msg, "Heap dump file created [%s bytes in %3.3f secs]",
-        JLONG_FORMAT, timer()->seconds());
-PRAGMA_DIAG_PUSH
-PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
-      tty->print_cr(msg, writer.bytes_written());
-PRAGMA_DIAG_POP
+      tty->print_cr("Heap dump file created [" JLONG_FORMAT " bytes in %3.3f secs]",
+                    writer.bytes_written(), timer()->seconds());
     } else {
       tty->print_cr("Dump file is incomplete: %s", writer.error());
     }
--- a/hotspot/src/share/vm/services/serviceUtil.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/services/serviceUtil.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,13 +57,13 @@
       if (k->is_klass()) {
         // if it's a class for an object, an object array, or
         // primitive (type) array then it's visible.
-        if (k->oop_is_instance()) {
+        if (k->is_instance_klass()) {
           return true;
         }
-        if (k->oop_is_objArray()) {
+        if (k->is_objArray_klass()) {
           return true;
         }
-        if (k->oop_is_typeArray()) {
+        if (k->is_typeArray_klass()) {
           return true;
         }
       }
--- a/hotspot/src/share/vm/services/threadService.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/services/threadService.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -505,8 +505,7 @@
   int len = (_locked_monitors != NULL ? _locked_monitors->length() : 0);
   for (int i = 0; i < len; i++) {
     oop o = _locked_monitors->at(i);
-    InstanceKlass* ik = InstanceKlass::cast(o->klass());
-    st->print_cr("\t- locked <" INTPTR_FORMAT "> (a %s)", p2i(o), ik->external_name());
+    st->print_cr("\t- locked <" INTPTR_FORMAT "> (a %s)", p2i(o), o->klass()->external_name());
   }
 
 }
@@ -729,8 +728,7 @@
 
   for (int i = 0; i < locks->length(); i++) {
     instanceOop obj = locks->at(i);
-    InstanceKlass* ik = InstanceKlass::cast(obj->klass());
-    st->print_cr("\t- <" INTPTR_FORMAT "> (a %s)", p2i(obj), ik->external_name());
+    st->print_cr("\t- <" INTPTR_FORMAT "> (a %s)", p2i(obj), obj->klass()->external_name());
   }
   st->cr();
 }
@@ -887,7 +885,7 @@
       oop obj = (oop)waitingToLockMonitor->object();
       if (obj != NULL) {
         st->print(" (object " INTPTR_FORMAT ", a %s)", p2i(obj),
-                   (InstanceKlass::cast(obj->klass()))->external_name());
+                   obj->klass()->external_name());
 
         if (!currentThread->current_pending_monitor_is_from_java()) {
           owner_desc = "\n  in JNI, which is held by";
@@ -911,7 +909,7 @@
     } else {
       st->print("  waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)",
                 p2i(waitingToLockBlocker),
-                (InstanceKlass::cast(waitingToLockBlocker->klass()))->external_name());
+                waitingToLockBlocker->klass()->external_name());
       assert(waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass()),
              "Must be an AbstractOwnableSynchronizer");
       oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker);
--- a/hotspot/src/share/vm/services/threadService.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/services/threadService.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -425,12 +425,12 @@
   }
 
   JavaThreadStatusChanger(JavaThread* java_thread,
-                          java_lang_Thread::ThreadStatus state) {
+                          java_lang_Thread::ThreadStatus state) : _old_state(java_lang_Thread::NEW) {
     save_old_state(java_thread);
     set_thread_status(state);
   }
 
-  JavaThreadStatusChanger(JavaThread* java_thread) {
+  JavaThreadStatusChanger(JavaThread* java_thread) : _old_state(java_lang_Thread::NEW) {
     save_old_state(java_thread);
   }
 
@@ -527,7 +527,7 @@
   // Current thread is the notifying thread which holds the monitor.
   static bool wait_reenter_begin(JavaThread *java_thread, ObjectMonitor *obj_m) {
     assert((java_thread != NULL), "Java thread should not be null here");
-    bool active  = false;
+    bool active = false;
     if (is_alive(java_thread) && ServiceUtil::visible_oop((oop)obj_m->object())) {
       active = contended_enter_begin(java_thread);
     }
@@ -542,7 +542,7 @@
   }
 
   JavaThreadBlockedOnMonitorEnterState(JavaThread *java_thread, ObjectMonitor *obj_m) :
-    JavaThreadStatusChanger(java_thread) {
+    _stat(NULL), _active(false), JavaThreadStatusChanger(java_thread) {
     assert((java_thread != NULL), "Java thread should not be null here");
     // Change thread status and collect contended enter stats for monitor contended
     // enter done for external java world objects and it is contended. All other cases
--- a/hotspot/src/share/vm/services/writeableFlags.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/services/writeableFlags.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -57,7 +57,6 @@
   }
 }
 
-PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
 static void print_flag_error_message_if_needed(Flag::Error error, const char* name, FormatBuffer<80>& err_msg) {
   if (error == Flag::SUCCESS) {
     return;
--- a/hotspot/src/share/vm/shark/sharkCompiler.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/shark/sharkCompiler.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2008, 2009, 2010, 2011 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -223,7 +223,7 @@
 }
 
 nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm,
-                                                methodHandle    target,
+                                                const methodHandle& target,
                                                 int             compile_id,
                                                 BasicType*      arg_types,
                                                 BasicType       return_type) {
--- a/hotspot/src/share/vm/shark/sharkCompiler.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/shark/sharkCompiler.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2008, 2009, 2010, 2011 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -47,7 +47,7 @@
   // Missing feature tests
   bool supports_native() { return true; }
   bool supports_osr()    { return true; }
-  bool can_compile_method(methodHandle method)  {
+  bool can_compile_method(const methodHandle& method)  {
     return ! (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form());
   }
 
@@ -62,7 +62,7 @@
 
   // Generate a wrapper for a native (JNI) method
   nmethod* generate_native_wrapper(MacroAssembler* masm,
-                                   methodHandle    target,
+                                   const methodHandle& target,
                                    int             compile_id,
                                    BasicType*      arg_types,
                                    BasicType       return_type);
--- a/hotspot/src/share/vm/shark/sharkIntrinsics.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/shark/sharkIntrinsics.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -65,7 +65,7 @@
   case vmIntrinsics::_currentThread:
     return true;
 
-    // sun.misc.Unsafe
+    // Unsafe
   case vmIntrinsics::_compareAndSwapInt:
     return true;
 
@@ -139,7 +139,7 @@
     do_Thread_currentThread();
     break;
 
-    // sun.misc.Unsafe
+    // Unsafe
   case vmIntrinsics::_compareAndSwapInt:
     do_Unsafe_compareAndSwapInt();
     break;
--- a/hotspot/src/share/vm/utilities/exceptions.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/utilities/exceptions.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -222,7 +222,7 @@
 }
 
 
-void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line, methodHandle method) {
+void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line, const methodHandle& method) {
   Handle exception;
   if (!THREAD->has_pending_exception()) {
     Klass* k = SystemDictionary::StackOverflowError_klass();
@@ -502,5 +502,5 @@
       message = java_lang_String::as_utf8_string(msg);
     }
   }
-  debug_check_abort(InstanceKlass::cast(exception()->klass())->external_name(), message);
+  debug_check_abort(exception()->klass()->external_name(), message);
 }
--- a/hotspot/src/share/vm/utilities/exceptions.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/utilities/exceptions.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -163,7 +163,7 @@
                               const char* message,
                               ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);
 
-  static void throw_stack_overflow_exception(Thread* thread, const char* file, int line, methodHandle method);
+  static void throw_stack_overflow_exception(Thread* thread, const char* file, int line, const methodHandle& method);
 
   // Exception counting for error files of interesting exceptions that may have
   // caused a problem for the jvm
--- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -287,8 +287,6 @@
 // Tested to work with clang version 3.1 and better.
 #define PRAGMA_DIAG_PUSH             _Pragma("GCC diagnostic push")
 #define PRAGMA_DIAG_POP              _Pragma("GCC diagnostic pop")
-#define PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL
-#define PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL PRAGMA_FORMAT_NONLITERAL_IGNORED
 
 // Hack to deal with gcc yammering about non-security format stuff
 #else
@@ -297,8 +295,6 @@
 // versions of the macro-pragma to obtain better checking with newer compilers.
 #define PRAGMA_DIAG_PUSH
 #define PRAGMA_DIAG_POP
-#define PRAGMA_FORMAT_NONLITERAL_IGNORED_EXTERNAL PRAGMA_FORMAT_NONLITERAL_IGNORED
-#define PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL
 #endif
 
 #if (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)
--- a/hotspot/src/share/vm/utilities/utf8.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/utilities/utf8.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +27,7 @@
 
 // Assume the utf8 string is in legal form and has been
 // checked in the class file parser/format checker.
-char* UTF8::next(const char* str, jchar* value) {
+template<typename T> char* UTF8::next(const char* str, T* value) {
   unsigned const char *ptr = (const unsigned char *)str;
   unsigned char ch, ch2, ch3;
   int length = -1;              /* bad length */
@@ -68,11 +68,11 @@
   } /* end of switch */
 
   if (length <= 0) {
-    *value = ptr[0];    /* default bad result; */
+    *value = (T)ptr[0];    /* default bad result; */
     return (char*)(ptr + 1); // make progress somehow
   }
 
-  *value = result;
+  *value = (T)result;
 
   // The assert is correct but the .class file is wrong
   // assert(UNICODE::utf8_size(result) == length, "checking reverse computation");
@@ -96,12 +96,22 @@
 // Count bytes of the form 10xxxxxx and deduct this count
 // from the total byte count.  The utf8 string must be in
 // legal form which has been verified in the format checker.
-int UTF8::unicode_length(const char* str, int len) {
+int UTF8::unicode_length(const char* str, int len, bool& is_latin1, bool& has_multibyte) {
   int num_chars = len;
+  has_multibyte = false;
+  is_latin1 = true;
+  unsigned char prev = 0;
   for (int i = 0; i < len; i++) {
-    if ((str[i] & 0xC0) == 0x80) {
+    unsigned char c = str[i];
+    if ((c & 0xC0) == 0x80) {
+      // Multibyte, check if valid latin1 character.
+      has_multibyte = true;
+      if (prev > 0xC3) {
+        is_latin1 = false;
+      }
       --num_chars;
     }
+    prev = c;
   }
   return num_chars;
 }
@@ -110,17 +120,28 @@
 // 10xxxxxx which only appear in multibyte characters.
 // The utf8 string must be in legal form and has been
 // verified in the format checker.
-int UTF8::unicode_length(const char* str) {
+int UTF8::unicode_length(const char* str, bool& is_latin1, bool& has_multibyte) {
   int num_chars = 0;
+  has_multibyte = false;
+  is_latin1 = true;
+  unsigned char prev = 0;
   for (const char* p = str; *p; p++) {
-    if (((*p) & 0xC0) != 0x80) {
+    unsigned char c = (*p);
+    if ((c & 0xC0) == 0x80) {
+      // Multibyte, check if valid latin1 character.
+      has_multibyte = true;
+      if (prev > 0xC3) {
+        is_latin1 = false;
+      }
+    } else {
       num_chars++;
     }
+    prev = c;
   }
   return num_chars;
 }
 
-// Writes a jchar a utf8 and returns the end
+// Writes a jchar as utf8 and returns the end
 static u_char* utf8_write(u_char* base, jchar ch) {
   if ((ch != 0) && (ch <=0x7f)) {
     base[0] = (u_char) ch;
@@ -145,7 +166,7 @@
   return base + 3;
 }
 
-void UTF8::convert_to_unicode(const char* utf8_str, jchar* unicode_str, int unicode_length) {
+template<typename T> void UTF8::convert_to_unicode(const char* utf8_str, T* unicode_str, int unicode_length) {
   unsigned char ch;
   const char *ptr = utf8_str;
   int index = 0;
@@ -153,7 +174,7 @@
   /* ASCII case loop optimization */
   for (; index < unicode_length; index++) {
     if((ch = ptr[0]) > 0x7F) { break; }
-    unicode_str[index] = ch;
+    unicode_str[index] = (T)ch;
     ptr = (const char *)(ptr + 1);
   }
 
@@ -162,6 +183,12 @@
   }
 }
 
+// Explicit instantiation for all supported string types.
+template char* UTF8::next<jchar>(const char* str, jchar* value);
+template char* UTF8::next<jbyte>(const char* str, jbyte* value);
+template void UTF8::convert_to_unicode<jchar>(const char* utf8_str, jchar* unicode_str, int unicode_length);
+template void UTF8::convert_to_unicode<jbyte>(const char* utf8_str, jbyte* unicode_str, int unicode_length);
+
 // returns the quoted ascii length of a 0-terminated utf8 string
 int UTF8::quoted_ascii_length(const char* utf8_str, int utf8_length) {
   const char *ptr = utf8_str;
@@ -306,9 +333,20 @@
                  + ((str[4] & 0x0f) << 6)  + (str[5] & 0x3f);
 }
 
-
 //-------------------------------------------------------------------------------------
 
+bool UNICODE::is_latin1(jchar c) {
+  return (c <= 0x00FF);
+}
+
+bool UNICODE::is_latin1(jchar* base, int length) {
+  for (int index = 0; index < length; index++) {
+    if (base[index] > 0x00FF) {
+      return false;
+    }
+  }
+  return true;
+}
 
 int UNICODE::utf8_size(jchar c) {
   if ((0x0001 <= c) && (c <= 0x007F)) return 1;
@@ -316,6 +354,11 @@
   return 3;
 }
 
+int UNICODE::utf8_size(jbyte c) {
+  if (c >= 0x0001) return 1;
+  return 2;
+}
+
 int UNICODE::utf8_length(jchar* base, int length) {
   int result = 0;
   for (int index = 0; index < length; index++) {
@@ -327,6 +370,15 @@
   return result;
 }
 
+int UNICODE::utf8_length(jbyte* base, int length) {
+  int result = 0;
+  for (int index = 0; index < length; index++) {
+    jbyte c = base[index];
+    result += utf8_size(c);
+  }
+  return result;
+}
+
 char* UNICODE::as_utf8(jchar* base, int length) {
   int utf8_len = utf8_length(base, length);
   u_char* buf = NEW_RESOURCE_ARRAY(u_char, utf8_len + 1);
@@ -335,6 +387,26 @@
   return result;
 }
 
+char* UNICODE::as_utf8(jbyte* base, int length) {
+  int utf8_len = utf8_length(base, length);
+  u_char* result = NEW_RESOURCE_ARRAY(u_char, utf8_len + 1);
+  u_char* p = result;
+  if (utf8_len == length) {
+    for (int index = 0; index < length; index++) {
+      *p++ = base[index];
+    }
+  } else {
+    // Unicode string contains U+0000 which should
+    // be encoded as 0xC080 in "modified" UTF8.
+    for (int index = 0; index < length; index++) {
+      p = utf8_write(p, ((jchar) base[index]) & 0xff);
+    }
+  }
+  *p = '\0';
+  assert(p == &result[utf8_len], "length prediction must be correct");
+  return (char*) result;
+}
+
 char* UNICODE::as_utf8(jchar* base, int length, char* buf, int buflen) {
   u_char* p = (u_char*)buf;
   for (int index = 0; index < length; index++) {
@@ -347,6 +419,26 @@
   return buf;
 }
 
+char* UNICODE::as_utf8(jbyte* base, int length, char* buf, int buflen) {
+  u_char* p = (u_char*)buf;
+  u_char* end = (u_char*)buf + buflen;
+  for (int index = 0; index < length; index++) {
+    jbyte c = base[index];
+    int sz = utf8_size(c);
+    buflen -= sz;
+    if (buflen <= 0) break; // string is truncated
+    if (sz == 1) {
+      *p++ = c;
+    } else {
+      // Unicode string contains U+0000 which should
+      // be encoded as 0xC080 in "modified" UTF8.
+      p = utf8_write(p, ((jchar) c) & 0xff);
+    }
+  }
+  *p = '\0';
+  return buf;
+}
+
 void UNICODE::convert_to_utf8(const jchar* base, int length, char* utf8_buffer) {
   for(int index = 0; index < length; index++) {
     utf8_buffer = (char*)utf8_write((u_char*)utf8_buffer, base[index]);
@@ -355,10 +447,11 @@
 }
 
 // returns the quoted ascii length of a unicode string
-int UNICODE::quoted_ascii_length(jchar* base, int length) {
+template<typename T>
+int UNICODE::quoted_ascii_length(T* base, int length) {
   int result = 0;
   for (int i = 0; i < length; i++) {
-    jchar c = base[i];
+    T c = base[i];
     if (c >= 32 && c < 127) {
       result++;
     } else {
@@ -368,12 +461,13 @@
   return result;
 }
 
-// converts a utf8 string to quoted ascii
-void UNICODE::as_quoted_ascii(const jchar* base, int length, char* buf, int buflen) {
+// converts a unicode string to quoted ascii
+template<typename T>
+void UNICODE::as_quoted_ascii(const T* base, int length, char* buf, int buflen) {
   char* p = buf;
   char* end = buf + buflen;
   for (int index = 0; index < length; index++) {
-    jchar c = base[index];
+    T c = base[index];
     if (c >= 32 && c < 127) {
       if (p + 1 >= end) break;      // string is truncated
       *p++ = (char)c;
@@ -386,6 +480,13 @@
   *p = '\0';
 }
 
+// Explicit instantiation for all supported types.
+template int UNICODE::quoted_ascii_length<jbyte>(jbyte* base, int length);
+template int UNICODE::quoted_ascii_length<jchar>(jchar* base, int length);
+template void UNICODE::as_quoted_ascii<jbyte>(const jbyte* base, int length, char* buf, int buflen);
+template void UNICODE::as_quoted_ascii<jchar>(const jchar* base, int length, char* buf, int buflen);
+
+
 #ifndef PRODUCT
 void TestAsUtf8() {
   char res[60];
--- a/hotspot/src/share/vm/utilities/utf8.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/utilities/utf8.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,13 +33,21 @@
 class UTF8 : AllStatic {
  public:
   // returns the unicode length of a 0-terminated utf8 string
-  static int unicode_length(const char* utf8_str);
+  static int unicode_length(const char* utf8_str) {
+    bool is_latin1, has_multibyte;
+    return unicode_length(utf8_str, is_latin1, has_multibyte);
+  }
+  static int unicode_length(const char* utf8_str, bool& is_latin1, bool& has_multibyte);
 
   // returns the unicode length of a non-0-terminated utf8 string
-  static int unicode_length(const char* utf8_str, int len);
+  static int unicode_length(const char* utf8_str, int len) {
+    bool is_latin1, has_multibyte;
+    return unicode_length(utf8_str, len, is_latin1, has_multibyte);
+  }
+  static int unicode_length(const char* utf8_str, int len, bool& is_latin1, bool& has_multibyte);
 
   // converts a utf8 string to a unicode string
-  static void convert_to_unicode(const char* utf8_str, jchar* unicode_buffer, int unicode_length);
+  template<typename T> static void convert_to_unicode(const char* utf8_str, T* unicode_str, int unicode_length);
 
   // returns the quoted ascii length of a utf8 string
   static int quoted_ascii_length(const char* utf8_str, int utf8_length);
@@ -53,7 +61,7 @@
 
   // decodes the current utf8 character, stores the result in value,
   // and returns the end of the current utf8 chararacter.
-  static char* next(const char* str, jchar* value);
+  template<typename T> static char* next(const char* str, T* value);
 
   // decodes the current utf8 character, gets the supplementary character instead of
   // the surrogate pair when seeing a supplementary character in string,
@@ -76,11 +84,19 @@
 
 class UNICODE : AllStatic {
  public:
+  // checks if the given unicode character can be encoded as latin1
+  static bool is_latin1(jchar c);
+
+  // checks if the given string can be encoded as latin1
+  static bool is_latin1(jchar* base, int length);
+
   // returns the utf8 size of a unicode character
   static int utf8_size(jchar c);
+  static int utf8_size(jbyte c);
 
   // returns the utf8 length of a unicode string
   static int utf8_length(jchar* base, int length);
+  static int utf8_length(jbyte* base, int length);
 
   // converts a unicode string to utf8 string
   static void convert_to_utf8(const jchar* base, int length, char* utf8_buffer);
@@ -88,13 +104,15 @@
   // converts a unicode string to a utf8 string; result is allocated
   // in resource area unless a buffer is provided.
   static char* as_utf8(jchar* base, int length);
+  static char* as_utf8(jbyte* base, int length);
   static char* as_utf8(jchar* base, int length, char* buf, int buflen);
+  static char* as_utf8(jbyte* base, int length, char* buf, int buflen);
 
   // returns the quoted ascii length of a unicode string
-  static int quoted_ascii_length(jchar* base, int length);
+  template<typename T> static int quoted_ascii_length(T* base, int length);
 
-  // converts a utf8 string to quoted ascii
-  static void as_quoted_ascii(const jchar* base, int length, char* buf, int buflen);
+  // converts a unicode string to quoted ascii
+  template<typename T> static void as_quoted_ascii(const T* base, int length, char* buf, int buflen);
 };
 
 #endif // SHARE_VM_UTILITIES_UTF8_HPP
--- a/hotspot/src/share/vm/utilities/xmlstream.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/src/share/vm/utilities/xmlstream.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -340,6 +340,7 @@
   print_raw_cr(">");
 }
 
+// If you remove the PRAGMA, this fails to compile with clang-503.0.40.
 PRAGMA_DIAG_PUSH
 PRAGMA_FORMAT_NONLITERAL_IGNORED
 // ------------------------------------------------------------------
--- a/hotspot/test/Makefile	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/Makefile	Wed Jul 05 21:00:20 2017 +0200
@@ -243,6 +243,9 @@
 	$(ECHO) "Running tests: $@"
 	$(MAKE) -j 1 TEST_SELECTION=":$@" UNIQUE_DIR=$@ jtreg_tests;
 
+hotspot_internal:
+	$(ALT_OUTPUTDIR)/jdk/bin/java -XX:+ExecuteInternalVMTests -XX:+ShowMessageBoxOnError -version
+
 # Prep for output
 prep: clean
 	@$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
--- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java	Wed Jul 05 21:00:20 2017 +0200
@@ -33,11 +33,12 @@
  * @build sun.hotspot.WhiteBox.*
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *      -XX:-PrintAssembly -XX:CompileCommand=option,*.helper,bool,PrintAssembly,false
+ *      -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOff
  * @summary Test compiler control compatibility with compile command
  */
 
-// import jdk.test.lib.OutputAnalyzer;
 import jdk.test.lib.dcmd.CommandExecutor;
 import jdk.test.lib.dcmd.JMXExecutor;
 
--- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java	Wed Jul 05 21:00:20 2017 +0200
@@ -33,11 +33,12 @@
  * @build sun.hotspot.WhiteBox.*
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run testng/othervm -Xbootclasspath/a:. -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityCommandOn
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *      -XX:-PrintAssembly -XX:CompileCommand=print,*.* -XX:+WhiteBoxAPI
+ *      TestCompilerDirectivesCompatibilityCommandOn
  * @summary Test compiler control compatibility with compile command
  */
 
-// import jdk.test.lib.OutputAnalyzer;
 import jdk.test.lib.dcmd.CommandExecutor;
 import jdk.test.lib.dcmd.JMXExecutor;
 
--- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java	Wed Jul 05 21:00:20 2017 +0200
@@ -33,7 +33,8 @@
  * @build sun.hotspot.WhiteBox.*
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run testng/othervm -Xbootclasspath/a:. -XX:+PrintAssembly -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag
+ * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *      -XX:+PrintAssembly -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityFlag
  * @summary Test compiler control compatibility with compile command
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/string/TestStringIntrinsics.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.Arrays;
+
+/*
+ * @test
+ * @bug 8054307
+ * @summary Tests correctness of string related intrinsics and C2 optimizations.
+ * @run main/timeout=240 TestStringIntrinsics
+ */
+public class TestStringIntrinsics {
+
+    public enum Operation {
+        ARR_EQUALS_B, ARR_EQUALS_C, EQUALS, COMPARE_TO, INDEX_OF, INDEX_OF_CON_U, INDEX_OF_CON_L,
+        INDEX_OF_CON_UL, CONCAT, CONCAT_C, CONCAT_I, CONCAT_M, INDEX_OF_CHAR
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    @interface Test {
+        Operation op();
+        String constString() default "";
+        String[] inStrings() default {};
+        char[] inChars() default {};
+        int[] inInts() default {};
+        String[] outStrings() default {};
+    }
+
+    public static void main(String[] args) throws Exception {
+        new TestStringIntrinsics().run();
+    }
+
+    public void run() throws Exception {
+        // Build latin1 and UTF16 strings
+        StringBuilder latin1Builder = new StringBuilder();
+        for (int i = 0; i <= 255; ++i) {
+            latin1Builder.append((char) i);
+        }
+        String latin1 = latin1Builder.toString();
+        StringBuilder utf16Builder = new StringBuilder();
+        for (int i = 0; i <= 10000; ++i) {
+            utf16Builder.append((char) i);
+        }
+        String utf16 = utf16Builder.toString();
+
+        // Invoke test methods
+        for (Method m : TestStringIntrinsics.class.getMethods()) {
+            if (m.isAnnotationPresent(Test.class)) {
+                System.out.print("Checking " + m.getName() + "... ");
+                Operation op = m.getAnnotation(Test.class).op();
+                Test antn = m.getAnnotation(Test.class);
+                if (isStringConcatTest(op)) {
+                    checkStringConcat(op, m, antn);
+                } else {
+                    checkIntrinsics(op, m, latin1, utf16, antn);
+                }
+                System.out.println("Done.");
+            }
+        }
+    }
+
+    private boolean isStringConcatTest(Operation op) {
+        return op == Operation.CONCAT ||
+               op == Operation.CONCAT_C ||
+               op == Operation.CONCAT_I ||
+               op == Operation.CONCAT_M;
+    }
+
+    /**
+     * Checks correctness of the String.equals, String.compareTo and String.indexOf intrinsics.
+     * -XX:SpecialStringEquals
+     * -XX:SpecialStringCompareTo
+     * -XX:SpecialStringIndexOf
+     */
+    private void checkIntrinsics(Operation op, Method m, String latin1, String utf16, Test antn) throws Exception {
+        for (int i = 0; i < 50_000; ++i) {
+            // Copy and permute latin1 and UTF16 string
+            char[] arrL = latin1.toCharArray();
+            int indexL = i % arrL.length;
+            int mod = (arrL.length - arrL[indexL]);
+            int incL = i % ((mod != 0) ? mod : 1);
+            arrL[indexL] = (char) ((int) arrL[indexL] + incL);
+            String latin1Copy = String.valueOf(arrL);
+
+            char[] arrU = utf16.toCharArray();
+            int indexU = i % arrU.length;
+            mod = (arrU.length - arrU[indexU]);
+            int incU = i % ((mod != 0) ? mod : 1);
+            arrU[indexU] = (char) ((int) arrU[indexU] + incU);
+            String utf16Copy = String.valueOf(arrU);
+
+            switch (op) {
+            case ARR_EQUALS_B:
+                invokeAndCheck(m, (incL == 0), latin1.getBytes("ISO-8859-1"), latin1Copy.getBytes("ISO-8859-1"));
+                invokeAndCheck(m, true, new byte[] {1, 2, 3}, new byte[] {1, 2, 3});
+                invokeAndCheck(m, true, new byte[] {1}, new byte[] {1});
+                invokeAndCheck(m, true, new byte[] {}, new byte[] {});
+                break;
+            case ARR_EQUALS_C:
+                invokeAndCheck(m, (incU == 0), utf16.toCharArray(), arrU);
+                break;
+            case EQUALS:
+                invokeAndCheck(m, (incL == 0), latin1, latin1Copy);
+                invokeAndCheck(m, false, latin1, "");
+                invokeAndCheck(m, false, "", latin1);
+
+                invokeAndCheck(m, (incU == 0), utf16, utf16Copy);
+                invokeAndCheck(m, false, utf16, "");
+                invokeAndCheck(m, false, "", utf16);
+
+                invokeAndCheck(m, false, latin1, utf16);
+                break;
+            case COMPARE_TO:
+                invokeAndCheck(m, -incL, latin1, latin1Copy);
+                invokeAndCheck(m, latin1.length(), latin1, "");
+
+                invokeAndCheck(m, -incU, utf16, utf16Copy);
+                invokeAndCheck(m, utf16.length(), utf16, "");
+
+                // Cross coder
+                char cL = latin1.charAt(indexL);
+                char cU = utf16.charAt(indexU);
+                invokeAndCheck(m, cL - cU, latin1, latin1.replace(cL, cU));
+                invokeAndCheck(m, cU - cL, utf16, utf16.replace(cU, cL));
+
+                // Different lengths
+                invokeAndCheck(m, 1, "ABCD", "ABC");
+                invokeAndCheck(m, -1, "\uff21\uff22\uff23", "\uff21\uff22\uff23\uff24");
+                invokeAndCheck(m, 1, "ABC\uff24", "ABC");
+                invokeAndCheck(m, 3, "ABC\uff24\uff25\uff26", "ABC");
+                invokeAndCheck(m, -1, "ABC","ABC\uff24");
+                invokeAndCheck(m, -3, "ABC","ABC\uff24\uff25\uff26");
+                break;
+            case INDEX_OF:
+                invokeAndCheck(m, indexL, latin1, latin1.substring(indexL), (indexL > 42) ? 42 : 0);
+                invokeAndCheck(m, 0, latin1, "", 0);
+
+                invokeAndCheck(m, indexU, utf16, utf16.substring(indexU), (indexU > 42) ? 42 : 0);
+                invokeAndCheck(m, 0, utf16, "", 0);
+
+                // Cross coder
+                invokeAndCheck(m, -1, latin1.substring(0, indexL), utf16.substring(indexU), (indexL > 42) ? 42 : 0);
+                // Skip latin1 chars in utf16 string
+                int start = 256;
+                int end = indexU > start ? indexU : start;
+                invokeAndCheck(m, end-start, utf16.substring(start, end) + latin1.substring(indexL), latin1.substring(indexL), 0);
+                break;
+            case INDEX_OF_CON_L:
+                invokeAndCheck(m, antn.constString(), latin1);
+                break;
+            case INDEX_OF_CON_U:
+                invokeAndCheck(m, antn.constString(), utf16);
+                break;
+            case INDEX_OF_CON_UL:
+                invokeAndCheck(m, antn.constString(), utf16);
+                break;
+            case INDEX_OF_CHAR:
+                invokeAndCheck(m, 7, "abcdefg\uD800\uDC00", 65536, 0);
+                invokeAndCheck(m, -1, "abcdefg\uD800\uDC01", 65536, 0);
+                invokeAndCheck(m, -1, "abcdefg\uD800", 65536, 0);
+                invokeAndCheck(m, 3, "abc\u0107", 263, 0);
+                invokeAndCheck(m, -1, "abc\u0108", 263, 0);
+                invokeAndCheck(m, 7, "abcdefg\u0107", 263, 0);
+                invokeAndCheck(m, 7, "abcdefg\u0107", 263, -1);
+                invokeAndCheck(m, 0, "\u0107", 263, 0);
+                break;
+            default:
+                throw new RuntimeException("Unexpected operation.");
+            }
+        }
+    }
+
+    /**
+     * Checks correctness of the C2 string concatenation optimization.
+     * -XX:OptimizeStringConcat
+     */
+    private void checkStringConcat(Operation op, Method m, Test antn) throws Exception {
+        for (int i = 0; i < 50_000; ++i) {
+            String[] result = antn.outStrings();
+            switch(op) {
+            case CONCAT:
+                String[] strs = antn.inStrings();
+                for (int j = 0; j < strs.length; ++j) {
+                    invokeAndCheck(m, result[j], strs[j]);
+                }
+                break;
+            case CONCAT_C:
+                char[] ch = antn.inChars();
+                for (int j = 0; j < ch.length; ++j) {
+                    invokeAndCheck(m, result[j], ch[j]);
+                }
+                break;
+            case CONCAT_I:
+                int[] k = antn.inInts();
+                for (int j = 0; j < k.length; ++j) {
+                    invokeAndCheck(m, result[j], k[j]);
+                }
+                break;
+            case CONCAT_M:
+                strs = antn.inStrings();
+                ch = antn.inChars();
+                k = antn.inInts();
+                for (int j = 0; j < strs.length; ++j) {
+                    invokeAndCheck(m, result[j], strs[j], ch[j], k[j]);
+                }
+                break;
+            default:
+                throw new RuntimeException("Unexpected operation.");
+            }
+        }
+    }
+
+    /**
+     * Invokes method 'm' by passing arguments 'args' and checks if the
+     * returned value equals 'expectedResult'.
+     */
+    private void invokeAndCheck(Method m, Object expectedResult, Object... args) throws Exception {
+        Object result = m.invoke(null, args);
+        if (!result.equals(expectedResult)) {
+//            System.out.println("Expected:");
+//            System.out.println(expectedResult);
+//            System.out.println("Returned:");
+//            System.out.println(result);
+            throw new RuntimeException("Result of '" + m.getName() + "' not equal to expected value.");
+        }
+    }
+
+    /*
+     * Constants
+     */
+    static final char charU = '\uff21';
+    static final char charL = 'A';
+    static final String emptyString = "";
+    static final String stringL = "abcdefghijklmnop";
+    static final String stringSmallL = "abc";
+    static final String stringU = "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28";
+    static final String stringSmallU = "\u0f21\u0f22\u0f23";
+    static final int constInt = 123;
+    static final int constIntNeg = -123;
+
+    /*
+     * Arrays.equals
+     */
+    @Test(op = Operation.ARR_EQUALS_B)
+    public static boolean arrayEqualsB(byte[] a, byte[] b) {
+      return Arrays.equals(a, b);
+    }
+
+    @Test(op = Operation.ARR_EQUALS_C)
+    public static boolean arrayEqualsC(char[] a, char[] b) {
+      return Arrays.equals(a, b);
+    }
+
+    /*
+     * String.equals
+     */
+    @Test(op = Operation.EQUALS)
+    public static boolean equals(String a, String b) {
+        return a.equals(b);
+    }
+
+    /*
+     * String.compareTo
+     */
+    @Test(op = Operation.COMPARE_TO)
+    public static int compareTo(String a, String b) {
+        return a.compareTo(b);
+    }
+
+    /*
+     * String.indexOf
+     */
+    @Test(op = Operation.INDEX_OF)
+    public static int indexOf(String a, String b, int from) {
+        return a.indexOf(b, from);
+    }
+
+    @Test(op = Operation.INDEX_OF_CON_U, constString = stringSmallU)
+    public static String indexOfConstU(String a) {
+        int result = a.indexOf(stringSmallU);
+        return a.substring(result, result + stringSmallU.length());
+    }
+
+    @Test(op = Operation.INDEX_OF_CON_U, constString = stringU)
+    public static String indexOfConstLargeU(String a) {
+        int result = a.indexOf(stringU);
+        return a.substring(result, result + stringU.length());
+    }
+
+    @Test(op = Operation.INDEX_OF_CON_U, constString = emptyString)
+    public static String indexOfConstEmptyU(String a) {
+        int result = a.indexOf(emptyString);
+        return a.substring(result, result + emptyString.length());
+    }
+
+    @Test(op = Operation.INDEX_OF_CON_L, constString = stringSmallL)
+    public static String indexOfConstL(String a) {
+        int result = a.indexOf(stringSmallL);
+        return a.substring(result, result + stringSmallL.length());
+    }
+
+    @Test(op = Operation.INDEX_OF_CON_L, constString = stringL)
+    public static String indexOfConstLargeL(String a) {
+        int result = a.indexOf(stringL);
+        return a.substring(result, result + stringL.length());
+    }
+
+    @Test(op = Operation.INDEX_OF_CON_L, constString = emptyString)
+    public static String indexOfConstEmptyL(String a) {
+        int result = a.indexOf(emptyString);
+        return a.substring(result, result + emptyString.length());
+    }
+
+    @Test(op = Operation.INDEX_OF_CON_UL, constString = stringSmallL)
+    public static String indexOfConstUL(String a) {
+        int result = a.indexOf(stringSmallL);
+        return a.substring(result, result + stringSmallL.length());
+    }
+
+    @Test(op = Operation.INDEX_OF_CON_UL, constString = stringL)
+    public static String indexOfConstLargeUL(String a) {
+        int result = a.indexOf(stringL);
+        return a.substring(result, result + stringL.length());
+    }
+
+    @Test(op = Operation.INDEX_OF_CHAR)
+    public static int indexOfChar(String a, int ch, int from) {
+        return a.indexOf(ch, from);
+    }
+
+    /*
+     * String concatenation optimization
+     */
+    @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"ABC", "\uff21\uff22\uff23"})
+    public static String concatString(String a) {
+        return new StringBuilder().append(a).toString();
+    }
+
+    @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {""})
+    public static String concatStringEmpty(String a) {
+        return new StringBuilder().toString();
+    }
+
+    @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"null"})
+    public static String concatStringNull(String a) {
+        return new StringBuilder().append((String)null).toString();
+    }
+
+    @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"abcdefghijklmnopABCabc", "abcdefghijklmnop\uff21\uff22\uff23abc"})
+    public static String concatStringConstL(String a) {
+        return new StringBuilder().append(stringL).append(a).append(stringSmallL).toString();
+    }
+
+    @Test(op = Operation.CONCAT, inStrings = {"ABC", "\uff21\uff22\uff23"}, outStrings = {"\u0f21\u0f22\u0f23ABC\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28", "\u0f21\u0f22\u0f23\uff21\uff22\uff23\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"})
+    public static String concatStringConstU(String a) {
+        return new StringBuilder().append(stringSmallU).append(a).append(stringU).toString();
+    }
+
+    @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"A", "\uff21"})
+    public static String concatChar(char a) {
+        return new StringBuilder().append(a).toString();
+    }
+
+    @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"abcdefghijklmnopAabcA\uff21", "abcdefghijklmnop\uff21abcA\uff21"})
+    public static String concatCharConstL(char a) {
+        return new StringBuilder().append(stringL).append(a).append(stringSmallL).append(charL).append(charU).toString();
+    }
+
+    @Test(op = Operation.CONCAT_C, inChars = {'A', '\uff21'}, outStrings = {"\u0f21\u0f22\u0f23A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21A", "\u0f21\u0f22\u0f23\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21A"})
+    public static String concatCharConstU(char a) {
+        return new StringBuilder().append(stringSmallU).append(a).append(stringU).append(charU).append(charL).toString();
+    }
+
+    @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"-2147483648", "-42", "42", "2147483647"})
+    public static String concatInt(int a) {
+        return new StringBuilder().append(a).toString();
+    }
+
+    @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"abcdefghijklmnop-2147483648abc123-123", "abcdefghijklmnop-42abc123-123", "abcdefghijklmnop42abc123-123", "abcdefghijklmnop2147483647abc123-123"})
+    public static String concatIntConstL(int b) {
+        return new StringBuilder().append(stringL).append(b).append(stringSmallL).append(constInt).append(constIntNeg).toString();
+    }
+
+    @Test(op = Operation.CONCAT_I, inInts = {Integer.MIN_VALUE, -42, 42, Integer.MAX_VALUE}, outStrings = {"\u0f21\u0f22\u0f23-2147483648\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f23-42\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f2342\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123", "\u0f21\u0f22\u0f232147483647\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28123-123"})
+    public static String concatIntConstU(int b) {
+        return new StringBuilder().append(stringSmallU).append(b).append(stringU).append(constInt).append(constIntNeg).toString();
+    }
+
+    @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"nullabcabcdefghijklmnopA123-123"})
+    public static String concatConstL(String a) {
+        return new StringBuilder().append((String)null).append(stringSmallL).append(stringL).append(charL).append(constInt).append(constIntNeg).toString();
+    }
+
+    @Test(op = Operation.CONCAT, inStrings = {""}, outStrings = {"nullabcabcdefghijklmnop\u0f21\u0f22\u0f23\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A\uff21123-123"})
+    public static String concatConstU(String a) {
+        return new StringBuilder().append((String)null).append(stringSmallL).append(stringL).append(stringSmallU).append(stringU).append(charL).append(charU).append(constInt).append(constIntNeg).toString();
+    }
+
+    @Test(op = Operation.CONCAT_M,
+          inStrings = {"ABCDEFG", "ABCDEFG", "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28", "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"},
+          inChars = {'A', '\uff21', 'A', '\uff21'},
+          inInts = {Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE},
+          outStrings = {"ABCDEFGA-2147483648nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21ABCDEFGA-2147483648null",
+                        "ABCDEFG\uff212147483647nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21ABCDEFG\uff212147483647null",
+                        "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A-2147483648nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28A-2147483648null",
+            "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff212147483647nullabcdefghijklmnop123-123A\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff21\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28\uff212147483647null"})
+    public static String concatMixed(String a, char b, int c) {
+        return new StringBuilder().append(a).append(b).append(c).append((String)null)
+                .append(stringL).append(constInt).append(constIntNeg).append(charL).append(stringU).append(charU)
+                .append(a).append(b).append(c).append((String)null).toString();
+    }
+}
--- a/hotspot/test/compiler/intrinsics/unsafe/HeapByteBufferTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/intrinsics/unsafe/HeapByteBufferTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -23,21 +23,22 @@
 //
 //
 
-import jdk.test.lib.Utils;
-import static java.lang.Math.abs;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
 import static java.nio.ByteOrder.BIG_ENDIAN;
 import static java.nio.ByteOrder.LITTLE_ENDIAN;
+import java.nio.ByteOrder;
+import java.util.Arrays;
 import java.util.Random;
-import java.util.Arrays;
+import jdk.test.lib.Utils;
 
 /**
  * @test
  * @bug 8026049
  * @library /testlibrary
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses HeapByteBufferTest
- * @run main/othervm HeapByteBufferTest
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses -Djdk.test.lib.random.seed=0 HeapByteBufferTest
+ * @run main/othervm -Djdk.test.lib.random.seed=0 HeapByteBufferTest
  * @summary Verify that byte buffers are correctly accessed.
  */
 
@@ -345,7 +346,149 @@
         return result;
     }
 
+    enum PrimitiveType {
+        BYTE(1), CHAR(2), SHORT(2), INT(4), LONG(8), FLOAT(4), DOUBLE(8);
+
+        public final int size;
+        PrimitiveType(int size) {
+            this.size = size;
+        }
+    }
+
+    void getOne(ByteBuffer b, PrimitiveType t) {
+        switch (t) {
+        case BYTE: b.get(); break;
+        case CHAR: b.getChar(); break;
+        case SHORT: b.getShort(); break;
+        case INT: b.getInt(); break;
+        case LONG: b.getLong(); break;
+        case FLOAT: b.getFloat(); break;
+        case DOUBLE: b.getDouble(); break;
+        }
+    }
+
+    void putOne(ByteBuffer b, PrimitiveType t) {
+        switch (t) {
+        case BYTE: b.put((byte)0); break;
+        case CHAR: b.putChar('0'); break;
+        case SHORT: b.putShort((short)0); break;
+        case INT: b.putInt(0); break;
+        case LONG: b.putLong(0); break;
+        case FLOAT: b.putFloat(0); break;
+        case DOUBLE: b.putDouble(0); break;
+        }
+    }
+
+    void getOne(ByteBuffer b, PrimitiveType t, int index) {
+        switch (t) {
+        case BYTE: b.get(index); break;
+        case CHAR: b.getChar(index); break;
+        case SHORT: b.getShort(index); break;
+        case INT: b.getInt(index); break;
+        case LONG: b.getLong(index); break;
+        case FLOAT: b.getFloat(index); break;
+        case DOUBLE: b.getDouble(index); break;
+        }
+    }
+
+    void putOne(ByteBuffer b, PrimitiveType t, int index) {
+        switch (t) {
+        case BYTE: b.put(index, (byte)0); break;
+        case CHAR: b.putChar(index, '0'); break;
+        case SHORT: b.putShort(index, (short)0); break;
+        case INT: b.putInt(index, 0); break;
+        case LONG: b.putLong(index, 0); break;
+        case FLOAT: b.putFloat(index, 0); break;
+        case DOUBLE: b.putDouble(index, 0); break;
+        }
+    }
+
+    void checkBoundaryConditions() {
+        for (int i = 0; i < 100; i++) {
+            int bufSize = random.nextInt(16);
+            byte[] bytes = new byte[bufSize];
+            ByteBuffer buf = ByteBuffer.wrap(bytes);
+            for (int j = 0; j < 100; j++) {
+                int offset = random.nextInt(32) - 8;
+                for (PrimitiveType t : PrimitiveType.values()) {
+                    int threw = 0;
+                    try {
+                        try {
+                            buf.position(offset);
+                            getOne(buf, t);
+                        } catch (BufferUnderflowException e) {
+                            if (offset + t.size < bufSize)
+                                throw new RuntimeException
+                                    ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e);
+                            threw++;
+                        } catch (IllegalArgumentException e) {
+                            if (offset >= 0 && offset + t.size < bufSize)
+                                throw new RuntimeException
+                                    ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e);
+                            threw++;
+                        }
+
+                        try {
+                            buf.position(offset);
+                            putOne(buf, t);
+                        } catch (BufferOverflowException e) {
+                            if (offset + t.size < bufSize)
+                                throw new RuntimeException
+                                    ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e);
+                            threw++;
+                        } catch (IllegalArgumentException e) {
+                            if (offset >= 0 && offset + t.size < bufSize)
+                                throw new RuntimeException
+                                    ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e);
+                            threw++;
+                        }
+
+                        try {
+                            putOne(buf, t, offset);
+                        } catch (IndexOutOfBoundsException e) {
+                            if (offset >= 0 && offset + t.size < bufSize)
+                                throw new RuntimeException
+                                    ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e);
+                            threw++;
+                        }
+
+                        try {
+                            getOne(buf, t, offset);
+                        } catch (IndexOutOfBoundsException e) {
+                            if (offset >= 0 && offset + t.size < bufSize)
+                                throw new RuntimeException
+                                    ("type = " + t + ", offset = " + offset + ", bufSize = " + bufSize, e);
+                            threw++;
+                        }
+
+                        if (threw == 0) {
+                            // Make sure that we should not have thrown.
+                            if (offset < 0 || offset + t.size > bufSize) {
+                                throw new RuntimeException
+                                    ("should have thrown but did not, type = " + t
+                                     + ", offset = " + offset + ", bufSize = " + bufSize);
+                            }
+                        } else if (threw != 4) {
+                            // If one of the {get,put} operations threw
+                            // due to an invalid offset then all four of
+                            // them should have thrown.
+                            throw new RuntimeException
+                                ("should have thrown but at least one did not, type = " + t
+                                 + ", offset = " + offset + ", bufSize = " + bufSize);
+                        }
+                    } catch (Throwable th) {
+                        throw new RuntimeException
+                            ("unexpected throw: type  = " + t + ", offset = " + offset + ", bufSize = " + bufSize, th);
+
+                    }
+                }
+            }
+        }
+    }
+
     public void run() {
+        checkBoundaryConditions();
+
         for (int i = 0; i < data.capacity(); i += 8) {
             data.putLong(i, random.nextLong());
         }
--- a/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,32 +27,41 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
  * @library /testlibrary /../../test/lib /
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * @compile ./common/CompilerToVMHelper.java
+ * @run main ClassFileInstaller jdk.vm.ci.hotspot.CompilerToVMHelper
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ *      -XX:+EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      NO_SEC_MAN
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ *      -XX:+EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      NO_PERM
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ *      -XX:+EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      ALL_PERM
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ *      -XX:+EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      NO_JVMCI_ACCESS_PERM
- * @run main/othervm -XX:+UnlockExperimentalVMOptions
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -Xbootclasspath/a:.
+ *      -XX:-EnableJVMCI
  *      compiler.jvmci.SecurityRestrictionsTest
  *      NO_JVMCI
  */
 
 package compiler.jvmci;
 
-import jdk.vm.ci.hotspot.CompilerToVM;
 import jdk.test.lib.Utils;
 import java.lang.InternalError;
+import java.lang.reflect.Constructor;
 import java.security.AccessControlException;
 import java.security.Permission;
 import java.util.PropertyPermission;
 import java.util.function.Consumer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 public class SecurityRestrictionsTest {
 
@@ -164,7 +173,14 @@
                     }
                 }
             };
-            Utils.runAndCheckException(CompilerToVM::new, exceptionCheck);
+            Utils.runAndCheckException(() -> {
+                try {
+                    // CompilerToVM::<cinit> provokes CompilerToVM::<init>
+                    Class.forName("jdk.vm.ci.hotspot.CompilerToVMHelper");
+                } catch (ClassNotFoundException e) {
+                    throw new Error("TESTBUG : " + e, e);
+                }
+            }, exceptionCheck);
         }
 
         public SecurityManager getSecurityManager() {
--- a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,15 +27,16 @@
 import java.lang.reflect.Executable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 
 public class CTVMUtilities {
     /*
      * A method to return HotSpotResolvedJavaMethod object using class object
      * and method as input
      */
-    public static HotSpotResolvedJavaMethodImpl getResolvedMethod(Class<?> cls,
+    public static HotSpotResolvedJavaMethod getResolvedMethod(Class<?> cls,
             Executable method) {
         if (!(method instanceof Method || method instanceof Constructor)) {
             throw new Error("wrong executable type " + method.getClass());
@@ -54,8 +55,20 @@
         return CompilerToVMHelper.getResolvedJavaMethodAtSlot(cls, slot);
     }
 
-    public static HotSpotResolvedJavaMethodImpl getResolvedMethod(
+    public static HotSpotResolvedJavaMethod getResolvedMethod(
             Executable method) {
         return getResolvedMethod(method.getDeclaringClass(), method);
     }
+
+    public static InstalledCode getInstalledCode(String name, long address,
+            long entryPoint) {
+        return new InstalledCodeStub(name, address, entryPoint);
+    }
+    private static class InstalledCodeStub extends InstalledCode {
+        private InstalledCodeStub(String name, long address, long entryPoint) {
+            super(name);
+            this.address = address;
+            this.entryPoint = entryPoint;
+        }
+    }
 }
--- a/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,115 +26,120 @@
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.code.InvalidInstalledCodeException;
 import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.SpeculationLog;
 
-/*
+/**
  * A simple "proxy" class to get test access to CompilerToVM package-private methods
  */
 public class CompilerToVMHelper {
     public static final CompilerToVM CTVM = new CompilerToVM();
 
-    public static byte[] getBytecode(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.getBytecode(method);
+    public static byte[] getBytecode(HotSpotResolvedJavaMethod method) {
+        return CTVM.getBytecode((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static int getExceptionTableLength(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.getExceptionTableLength(method);
+    public static int getExceptionTableLength(HotSpotResolvedJavaMethod method) {
+        return CTVM.getExceptionTableLength((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.getExceptionTableStart(method);
+    public static long getExceptionTableStart(HotSpotResolvedJavaMethod method) {
+        return CTVM.getExceptionTableStart((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.canInlineMethod(method);
+    public static boolean canInlineMethod(HotSpotResolvedJavaMethod method) {
+        return CTVM.canInlineMethod((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static boolean shouldInlineMethod(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.shouldInlineMethod(method);
+    public static boolean shouldInlineMethod(HotSpotResolvedJavaMethod method) {
+        return CTVM.shouldInlineMethod((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static HotSpotResolvedJavaMethodImpl findUniqueConcreteMethod(
-            HotSpotResolvedObjectTypeImpl actualHolderType,
-            HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.findUniqueConcreteMethod(actualHolderType, method);
+    public static HotSpotResolvedJavaMethod findUniqueConcreteMethod(
+            HotSpotResolvedObjectType actualHolderType,
+            HotSpotResolvedJavaMethod method) {
+        return CTVM.findUniqueConcreteMethod((HotSpotResolvedObjectTypeImpl) actualHolderType, (HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static HotSpotResolvedObjectTypeImpl getImplementor(HotSpotResolvedObjectTypeImpl type) {
-        return CTVM.getImplementor(type);
+    public static HotSpotResolvedObjectType getImplementor(HotSpotResolvedObjectType type) {
+        return CTVM.getImplementor((HotSpotResolvedObjectTypeImpl) type);
     }
 
-    public static boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.methodIsIgnoredBySecurityStackWalk(method);
+    public static boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethod method) {
+        return CTVM.methodIsIgnoredBySecurityStackWalk((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static HotSpotResolvedObjectTypeImpl lookupType(String name,
+    public static HotSpotResolvedObjectType lookupType(String name,
             Class<?> accessingClass, boolean resolve) {
         return CTVM.lookupType(name, accessingClass, resolve);
     }
 
-    public static Object resolveConstantInPool(HotSpotConstantPool constantPool, int cpi) {
-        return CTVM.resolveConstantInPool(constantPool, cpi);
+    public static Object resolveConstantInPool(ConstantPool constantPool, int cpi) {
+        return CTVM.resolveConstantInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static Object resolvePossiblyCachedConstantInPool(HotSpotConstantPool constantPool, int cpi) {
-        return CTVM.resolvePossiblyCachedConstantInPool(constantPool, cpi);
+    public static Object resolvePossiblyCachedConstantInPool(ConstantPool constantPool, int cpi) {
+        return CTVM.resolvePossiblyCachedConstantInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static int lookupNameAndTypeRefIndexInPool(HotSpotConstantPool constantPool, int cpi) {
-        return CTVM.lookupNameAndTypeRefIndexInPool(constantPool, cpi);
+    public static int lookupNameAndTypeRefIndexInPool(ConstantPool constantPool, int cpi) {
+        return CTVM.lookupNameAndTypeRefIndexInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static String lookupNameInPool(HotSpotConstantPool constantPool, int cpi) {
-        return CTVM.lookupNameInPool(constantPool, cpi);
+    public static String lookupNameInPool(ConstantPool constantPool, int cpi) {
+        return CTVM.lookupNameInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static String lookupSignatureInPool(HotSpotConstantPool constantPool, int cpi) {
-        return CTVM.lookupSignatureInPool(constantPool, cpi);
+    public static String lookupSignatureInPool(ConstantPool constantPool, int cpi) {
+        return CTVM.lookupSignatureInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static int lookupKlassRefIndexInPool(HotSpotConstantPool constantPool, int cpi) {
-        return CTVM.lookupKlassRefIndexInPool(constantPool, cpi);
+    public static int lookupKlassRefIndexInPool(ConstantPool constantPool, int cpi) {
+        return CTVM.lookupKlassRefIndexInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static Object lookupKlassInPool(HotSpotConstantPool constantPool, int cpi) {
-        return CTVM.lookupKlassInPool(constantPool, cpi);
+    public static Object lookupKlassInPool(ConstantPool constantPool, int cpi) {
+        return CTVM.lookupKlassInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static HotSpotResolvedJavaMethodImpl lookupMethodInPool(
-            HotSpotConstantPool constantPool, int cpi, byte opcode) {
-        return CTVM.lookupMethodInPool(constantPool, cpi, opcode);
+    public static HotSpotResolvedJavaMethod lookupMethodInPool(
+            ConstantPool constantPool, int cpi, byte opcode) {
+        return CTVM.lookupMethodInPool((HotSpotConstantPool) constantPool, cpi, opcode);
     }
 
-    public static void resolveInvokeDynamicInPool(HotSpotConstantPool constantPool, int cpi) {
-        CTVM.resolveInvokeDynamicInPool(constantPool, cpi);
+    public static void resolveInvokeDynamicInPool(
+            ConstantPool constantPool, int cpi) {
+        CTVM.resolveInvokeDynamicInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static void resolveInvokeHandleInPool(HotSpotConstantPool constantPool, int cpi) {
-        CTVM.resolveInvokeHandleInPool(constantPool, cpi);
+    public static void resolveInvokeHandleInPool(
+            ConstantPool constantPool, int cpi) {
+        CTVM.resolveInvokeHandleInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static HotSpotResolvedObjectTypeImpl resolveTypeInPool(
-            HotSpotConstantPool constantPool, int cpi) throws LinkageError {
-        return CTVM.resolveTypeInPool(constantPool, cpi);
+    public static HotSpotResolvedObjectType resolveTypeInPool(
+            ConstantPool constantPool, int cpi) {
+        return CTVM.resolveTypeInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
-    public static HotSpotResolvedObjectTypeImpl resolveFieldInPool(
-            HotSpotConstantPool constantPool, int cpi, byte opcode, long[] info) {
-        return CTVM.resolveFieldInPool(constantPool, cpi, opcode, info);
+    public static HotSpotResolvedObjectType resolveFieldInPool(
+            ConstantPool constantPool, int cpi, byte opcode, long[] info) {
+        return CTVM.resolveFieldInPool((HotSpotConstantPool) constantPool, cpi, opcode, info);
     }
 
     public static int constantPoolRemapInstructionOperandFromCache(
-            HotSpotConstantPool constantPool, int cpci) {
-        return CTVM.constantPoolRemapInstructionOperandFromCache(constantPool, cpci);
+            ConstantPool constantPool, int cpci) {
+        return CTVM.constantPoolRemapInstructionOperandFromCache((HotSpotConstantPool) constantPool, cpci);
     }
 
-    public static Object lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi) {
-        return CTVM.lookupAppendixInPool(constantPool, cpi);
+    public static Object lookupAppendixInPool(
+            ConstantPool constantPool, int cpi) {
+        return CTVM.lookupAppendixInPool((HotSpotConstantPool) constantPool, cpi);
     }
 
     public static int installCode(TargetDescription target,
-            HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog) {
+            HotSpotCompiledCode compiledCode, InstalledCode code, HotSpotSpeculationLog speculationLog) {
         return CTVM.installCode(target, compiledCode, code, speculationLog);
     }
 
@@ -144,10 +149,10 @@
     }
 
     public static void notifyCompilationStatistics(int id,
-            HotSpotResolvedJavaMethodImpl method, boolean osr,
+            HotSpotResolvedJavaMethod method, boolean osr,
             int processedBytecodes, long time, long timeUnitsPerSecond,
             InstalledCode installedCode) {
-        CTVM.notifyCompilationStatistics(id, method, osr, processedBytecodes,
+        CTVM.notifyCompilationStatistics(id, (HotSpotResolvedJavaMethodImpl) method, osr, processedBytecodes,
                 time, timeUnitsPerSecond, installedCode);
     }
 
@@ -155,28 +160,28 @@
         CTVM.resetCompilationStatistics();
     }
 
-    public static long initializeConfiguration() {
-        return CTVM.initializeConfiguration();
+    public static long initializeConfiguration(HotSpotVMConfig config) {
+        return CTVM.initializeConfiguration(config);
     }
 
-    public static HotSpotResolvedJavaMethodImpl resolveMethod(
-            HotSpotResolvedObjectTypeImpl exactReceiver,
-            HotSpotResolvedJavaMethodImpl method,
-            HotSpotResolvedObjectTypeImpl caller) {
-        return CTVM.resolveMethod(exactReceiver, method, caller);
+    public static HotSpotResolvedJavaMethod resolveMethod(
+            HotSpotResolvedObjectType exactReceiver,
+            HotSpotResolvedJavaMethod method,
+            HotSpotResolvedObjectType caller) {
+        return CTVM.resolveMethod((HotSpotResolvedObjectTypeImpl) exactReceiver, (HotSpotResolvedJavaMethodImpl) method, (HotSpotResolvedObjectTypeImpl) caller);
     }
 
-    public static HotSpotResolvedJavaMethodImpl getClassInitializer(
-            HotSpotResolvedObjectTypeImpl type) {
-        return CTVM.getClassInitializer(type);
+    public static HotSpotResolvedJavaMethod getClassInitializer(
+            HotSpotResolvedObjectType type) {
+        return CTVM.getClassInitializer((HotSpotResolvedObjectTypeImpl) type);
     }
 
-    public static boolean hasFinalizableSubclass(HotSpotResolvedObjectTypeImpl type) {
-        return CTVM.hasFinalizableSubclass(type);
+    public static boolean hasFinalizableSubclass(HotSpotResolvedObjectType type) {
+        return CTVM.hasFinalizableSubclass((HotSpotResolvedObjectTypeImpl) type);
     }
 
-    public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethodAtSlot(Class<?> holder,
-            int slot) {
+    public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethodAtSlot(
+            Class<?> holder, int slot) {
         return CTVM.getResolvedJavaMethodAtSlot(holder, slot);
     }
 
@@ -184,13 +189,13 @@
         return CTVM.getMaxCallTargetOffset(address);
     }
 
-    public static String disassembleCodeBlob(long codeBlob) {
+    public static String disassembleCodeBlob(InstalledCode codeBlob) {
         return CTVM.disassembleCodeBlob(codeBlob);
     }
 
     public static StackTraceElement getStackTraceElement(
-            HotSpotResolvedJavaMethodImpl method, int bci) {
-        return CTVM.getStackTraceElement(method, bci);
+            HotSpotResolvedJavaMethod method, int bci) {
+        return CTVM.getStackTraceElement((HotSpotResolvedJavaMethodImpl)method, bci);
     }
 
     public static Object executeInstalledCode(Object[] args,
@@ -198,28 +203,28 @@
         return CTVM.executeInstalledCode(args, installedCode);
     }
 
-    public static long[] getLineNumberTable(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.getLineNumberTable(method);
+    public static long[] getLineNumberTable(HotSpotResolvedJavaMethod method) {
+        return CTVM.getLineNumberTable((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static int getLocalVariableTableLength(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.getLocalVariableTableLength(method);
+    public static int getLocalVariableTableLength(HotSpotResolvedJavaMethod method) {
+        return CTVM.getLocalVariableTableLength((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.getLocalVariableTableStart(method);
+    public static long getLocalVariableTableStart(HotSpotResolvedJavaMethod method) {
+        return CTVM.getLocalVariableTableStart((HotSpotResolvedJavaMethodImpl)method);
     }
 
     public static Object readUncompressedOop(long address) {
         return CTVM.readUncompressedOop(address);
     }
 
-    public static void doNotInlineOrCompile(HotSpotResolvedJavaMethodImpl method) {
-        CTVM.doNotInlineOrCompile(method);
+    public static void doNotInlineOrCompile(HotSpotResolvedJavaMethod method) {
+        CTVM.doNotInlineOrCompile((HotSpotResolvedJavaMethodImpl)method);
     }
 
-    public static void reprofile(HotSpotResolvedJavaMethodImpl method) {
-        CTVM.reprofile(method);
+    public static void reprofile(HotSpotResolvedJavaMethod method) {
+        CTVM.reprofile((HotSpotResolvedJavaMethodImpl)method);
     }
 
     public static void invalidateInstalledCode(InstalledCode installedCode) {
@@ -234,14 +239,14 @@
         return CTVM.isMature(metaspaceMethodData);
     }
 
-    public static int allocateCompileId(HotSpotResolvedJavaMethodImpl method,
+    public static int allocateCompileId(HotSpotResolvedJavaMethod method,
             int entryBCI) {
-        return CTVM.allocateCompileId(method, entryBCI);
+        return CTVM.allocateCompileId((HotSpotResolvedJavaMethodImpl) method, entryBCI);
     }
 
     public static boolean hasCompiledCodeForOSR(
-            HotSpotResolvedJavaMethodImpl method, int entryBCI, int level) {
-        return CTVM.hasCompiledCodeForOSR(method, entryBCI, level);
+            HotSpotResolvedJavaMethod method, int entryBCI, int level) {
+        return CTVM.hasCompiledCodeForOSR((HotSpotResolvedJavaMethodImpl) method, entryBCI, level);
     }
 
     public static String getSymbol(long metaspaceSymbol) {
@@ -250,7 +255,7 @@
 
     public static HotSpotStackFrameReference getNextStackFrame(
             HotSpotStackFrameReference frame,
-            HotSpotResolvedJavaMethodImpl[] methods, int initialSkip) {
+            ResolvedJavaMethod[] methods, int initialSkip) {
         return CTVM.getNextStackFrame(frame, methods, initialSkip);
     }
 
@@ -259,9 +264,9 @@
         CTVM.materializeVirtualObjects(stackFrame, invalidate);
     }
 
-    public static int getVtableIndexForInterfaceMethod(HotSpotResolvedObjectTypeImpl type,
-            HotSpotResolvedJavaMethodImpl method) {
-        return CTVM.getVtableIndexForInterfaceMethod(type, method);
+    public static int getVtableIndexForInterfaceMethod(HotSpotResolvedObjectType type,
+            HotSpotResolvedJavaMethod method) {
+        return CTVM.getVtableIndexForInterfaceMethod((HotSpotResolvedObjectTypeImpl) type, (HotSpotResolvedJavaMethodImpl) method);
     }
 
     public static boolean shouldDebugNonSafepoints() {
@@ -276,7 +281,7 @@
         CTVM.flushDebugOutput();
     }
 
-    public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base,
+    public static HotSpotResolvedJavaMethod getResolvedJavaMethod(Object base,
             long displacement) {
         return CTVM.getResolvedJavaMethod(base, displacement);
     }
@@ -285,8 +290,24 @@
         return CTVM.getConstantPool(base, displacement);
     }
 
-    public static HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base,
+    public static HotSpotResolvedObjectType getResolvedJavaType(Object base,
             long displacement, boolean compressed) {
         return CTVM.getResolvedJavaType(base, displacement, compressed);
     }
+
+    public static long getMetaspacePointer(Object o) {
+        return ((MetaspaceWrapperObject) o).getMetaspacePointer();
+    }
+
+    public static Class<?> CompilerToVMClass() {
+        return CompilerToVM.class;
+    }
+
+    public static Class<?> HotSpotConstantPoolClass() {
+        return HotSpotConstantPool.class;
+    }
+
+    public static Class<?> getMirror(HotSpotResolvedObjectType type) {
+        return ((HotSpotResolvedJavaType) type).mirror();
+    }
 }
--- a/hotspot/test/compiler/jvmci/common/JVMCIHelpers.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/common/JVMCIHelpers.java	Wed Jul 05 21:00:20 2017 +0200
@@ -24,10 +24,11 @@
 package compiler.jvmci.common;
 
 import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.hotspot.HotSpotVMEventListener;
-import jdk.vm.ci.compiler.Compiler;
-import jdk.vm.ci.compiler.CompilerFactory;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.runtime.JVMCICompiler;
+import jdk.vm.ci.runtime.JVMCICompilerFactory;
 import jdk.vm.ci.runtime.JVMCIRuntime;
 
 /*
@@ -39,16 +40,15 @@
         // just empty, using default interface methods
     }
 
-    public static class EmptyHotspotCompiler implements Compiler {
+    public static class EmptyHotspotCompiler implements JVMCICompiler {
 
         @Override
-        public void compileMethod(ResolvedJavaMethod method, int entryBCI,
-                long jvmciEnv, int id) {
+        public void compileMethod(CompilationRequest request) {
             // do nothing
         }
     }
 
-    public static class EmptyCompilerFactory implements CompilerFactory {
+    public static class EmptyCompilerFactory implements JVMCICompilerFactory {
 
         @Override
         public String getCompilerName() {
@@ -56,12 +56,7 @@
         }
 
         @Override
-        public Architecture initializeArchitecture(Architecture arch) {
-            return arch;
-        }
-
-        @Override
-        public Compiler createCompiler(JVMCIRuntime runtime) {
+        public JVMCICompiler createCompiler(JVMCIRuntime runtime) {
             return new EmptyHotspotCompiler();
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.vm.ci.hotspot;
+
+/**
+ * A public available version of MetaspaceWrapperObject interface.
+ */
+public interface PublicMetaspaceWrapperObject extends MetaspaceWrapperObject { }
--- a/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.Compiler	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
--- a/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.compiler.CompilerFactory	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.runtime.JVMCICompiler	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,1 @@
+compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/common/services/jdk.vm.ci.runtime.JVMCICompilerFactory	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,1 @@
+compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
--- a/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -34,6 +34,7 @@
  * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
  *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
  *      -XX:-BackgroundCompilation
+        -XX:+LogCompilation
  *      compiler.jvmci.compilerToVM.AllocateCompileIdTest
  */
 
@@ -51,7 +52,7 @@
 
 import compiler.jvmci.common.testcases.TestCase;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Pair;
 import jdk.test.lib.Utils;
@@ -74,8 +75,9 @@
         try {
             Class<?> aClass = DummyClass.class;
             Method method = aClass.getMethod("withLoop");
-            result.add(new CompileCodeTestCase(method, 17));
-            result.add(new CompileCodeTestCase(method, -1));
+            Object receiver = new DummyClass();
+            result.add(new CompileCodeTestCase(receiver, method, 17));
+            result.add(new CompileCodeTestCase(receiver, method, -1));
         } catch (NoSuchMethodException e) {
             throw new Error("TEST BUG : " + e, e);
         }
@@ -90,16 +92,19 @@
 
         try {
             Class<?> aClass = DummyClass.class;
+            Object receiver = new DummyClass();
             Method method = aClass.getMethod("dummyInstanceFunction");
             // greater than bytecode.length
             int[] bcis = new int[] {30, 50, 200};
             for (int bci : bcis) {
-                result.add(new Pair<>(new CompileCodeTestCase(method, bci),
+                result.add(new Pair<>(
+                        new CompileCodeTestCase(receiver, method, bci),
                         IllegalArgumentException.class));
             }
             bcis = new int[] {-4, -50, -200};
             for (int bci : bcis) {
-                result.add(new Pair<>(new CompileCodeTestCase(method, bci),
+                result.add(new Pair<>(
+                        new CompileCodeTestCase(receiver, method, bci),
                         IllegalArgumentException.class));
             }
         } catch (NoSuchMethodException e) {
@@ -111,8 +116,10 @@
     private void runSanityCorrectTest(CompileCodeTestCase testCase) {
         System.out.println(testCase);
         Executable aMethod = testCase.executable;
+        // to generate ciTypeFlow
+        System.out.println(testCase.invoke(Utils.getNullValues(aMethod.getParameterTypes())));
         int bci = testCase.bci;
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         int wbCompileID = getWBCompileID(testCase);
         int id = CompilerToVMHelper.allocateCompileId(method, bci);
@@ -140,7 +147,7 @@
         Class<? extends Throwable> exception = testCase.second;
         Executable aMethod = testCase.first.executable;
         int bci = testCase.first.bci;
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         Utils.runAndCheckException(
                 () -> CompilerToVMHelper.allocateCompileId(method, bci),
--- a/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -45,7 +45,7 @@
 import java.util.Arrays;
 import java.util.List;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.test.lib.Asserts;
 import sun.hotspot.WhiteBox;
 
@@ -59,7 +59,7 @@
     }
 
     private static void runSanityTest(Executable aMethod) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         boolean canInline = CompilerToVMHelper.canInlineMethod(method);
         boolean expectedCanInline = !WB.testSetDontInlineMethod(aMethod,
--- a/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java	Wed Jul 05 21:00:20 2017 +0200
@@ -24,12 +24,17 @@
 
 package compiler.jvmci.compilerToVM;
 
+import compiler.jvmci.common.CTVMUtilities;
 import compiler.testlibrary.CompilerUtils;
 import jdk.test.lib.Utils;
+import jdk.vm.ci.code.InstalledCode;
 import sun.hotspot.WhiteBox;
 import sun.hotspot.code.NMethod;
 
 import java.lang.reflect.Executable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -37,12 +42,12 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import jdk.test.lib.Pair;
 
 /**
  * A test case for tests which require compiled code.
  */
-public final class CompileCodeTestCase {
-    public static final Map<Class<?>, Object> RECEIVERS;
+public class CompileCodeTestCase {
     private static final WhiteBox WB = WhiteBox.getWhiteBox();
     private static final int COMP_LEVEL;
     static {
@@ -56,21 +61,51 @@
             Interface.class,
             Dummy.class,
             DummyEx.class};
+    private static final Map<Class<?>, Object> RECEIVERS;
 
+    public final Object receiver;
     public final Executable executable;
     public final int bci;
     private final boolean isOsr;
 
-    public CompileCodeTestCase(Executable executable, int bci) {
+    public CompileCodeTestCase(Object receiver, Executable executable,
+            int bci) {
+        this.receiver = receiver;
         this.executable = executable;
         this.bci = bci;
-        isOsr = bci >= 0;
+        isOsr = (bci >= 0);
     }
 
     public NMethod compile() {
         return compile(COMP_LEVEL);
     }
 
+    public Pair<Object, ? extends Throwable> invoke(Object[] args) {
+        boolean old = executable.isAccessible();
+        executable.setAccessible(true);
+        try {
+            try {
+                if (executable instanceof Method) {
+                    Method m = (Method) executable;
+                    return new Pair<>(m.invoke(receiver, args), null);
+                }
+
+                if (executable instanceof Constructor) {
+                    Constructor c = (Constructor) executable;
+                    return new Pair<>(c.newInstance(args), null);
+                }
+            } catch (InvocationTargetException e) {
+                return new Pair<>(null, e.getCause());
+            } catch (Throwable e) {
+                return new Pair<>(null, e);
+            }
+        } finally {
+            executable.setAccessible(old);
+        }
+        throw new Error(executable + " has unsupported type "
+                + executable.getClass());
+    }
+
     public NMethod compile(int level) {
         boolean enqueued = WB.enqueueMethodForCompilation(executable,
                 level, bci);
@@ -86,13 +121,17 @@
     public static List<CompileCodeTestCase> generate(int bci) {
         ArrayList<CompileCodeTestCase> result = new ArrayList<>();
         for (Class<?> aClass : CLASSES) {
+            Object receiver = RECEIVERS.get(aClass);
+            if (receiver == null) {
+                throw new Error("TESTBUG : no receiver for class " + aClass);
+            }
             for (Executable m : aClass.getDeclaredConstructors()) {
-                result.add(new CompileCodeTestCase(m, bci));
+                result.add(new CompileCodeTestCase(receiver, m, bci));
             }
             Arrays.stream(aClass.getDeclaredMethods())
                     .filter(m -> !Modifier.isAbstract(m.getModifiers()))
                     .filter(m -> !Modifier.isNative(m.getModifiers()))
-                    .map(m -> new CompileCodeTestCase(m, bci))
+                    .map(m -> new CompileCodeTestCase(receiver, m, bci))
                     .forEach(result::add);
         }
         return result;
@@ -102,6 +141,14 @@
         return NMethod.get(executable, isOsr);
     }
 
+    public InstalledCode toInstalledCode() {
+        NMethod nmethod = toNMethod();
+        long address = nmethod == null ? 0L : nmethod.address;
+        long entryPoint = nmethod == null ? 0L : nmethod.entry_point;
+        return CTVMUtilities.getInstalledCode(
+                executable.getName(), address, entryPoint);
+    }
+
     @Override
     public String toString() {
         return "CompileCodeTestCase{" +
--- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,8 +26,7 @@
 
 import java.util.HashMap;
 import java.util.Map;
-import jdk.vm.ci.hotspot.HotSpotConstantPool;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.internal.misc.SharedSecrets;
 import sun.reflect.ConstantPool;
 
@@ -35,15 +34,15 @@
  * Common class for jdk.vm.ci.hotspot.CompilerToVM constant pool tests
  */
 public class ConstantPoolTestCase {
-
     private final Map<ConstantPoolTestsHelper.ConstantTypes, Validator> typeTests;
 
     public static interface Validator {
-        void validate(HotSpotConstantPool constantPoolCTVM, ConstantPool constantPoolSS,
+        void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
+                ConstantPool constantPoolSS,
             ConstantPoolTestsHelper.DummyClasses dummyClass, int index);
     }
 
-    public ConstantPoolTestCase(Map<ConstantPoolTestsHelper.ConstantTypes, Validator> typeTests) {
+    public ConstantPoolTestCase(Map<ConstantPoolTestsHelper.ConstantTypes,Validator> typeTests) {
         this.typeTests = new HashMap<>();
         this.typeTests.putAll(typeTests);
     }
@@ -120,9 +119,10 @@
         for (ConstantPoolTestsHelper.DummyClasses dummyClass
                 : ConstantPoolTestsHelper.DummyClasses.values()) {
             System.out.printf("%nTesting dummy %s%n", dummyClass.klass);
-            HotSpotResolvedObjectTypeImpl holder = HotSpotResolvedObjectTypeImpl
+            HotSpotResolvedObjectType holder = HotSpotResolvedObjectType
                     .fromObjectClass(dummyClass.klass);
-            HotSpotConstantPool constantPoolCTVM = holder.getConstantPool();
+            jdk.vm.ci.meta.ConstantPool constantPoolCTVM
+                    = holder.getConstantPool();
             ConstantPool constantPoolSS = SharedSecrets.getJavaLangAccess().
                         getConstantPool(dummyClass.klass);
             for (Integer i : dummyClass.cp.keySet()) {
--- a/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -42,10 +42,12 @@
 package compiler.jvmci.compilerToVM;
 
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.code.InstalledCode;
 import jdk.test.lib.Asserts;
 import sun.hotspot.code.NMethod;
 
 import java.util.List;
+import jdk.test.lib.Utils;
 
 public class DisassembleCodeBlobTest {
 
@@ -56,12 +58,23 @@
                 = CompileCodeTestCase.generate(/* bci = */ -1);
         testCases.addAll(CompileCodeTestCase.generate(/* bci = */ 0));
         testCases.forEach(test::check);
+        testCases.stream().findAny().ifPresent(test::checkZero);
         test.checkNull();
     }
 
     private void checkNull() {
-        String str = CompilerToVMHelper.disassembleCodeBlob(0L);
-        Asserts.assertNull(str, "not null string returned for null pointer");
+        Utils.runAndCheckException(
+                () -> CompilerToVMHelper.disassembleCodeBlob(null),
+                NullPointerException.class);
+    }
+
+    private void checkZero(CompileCodeTestCase testCase) {
+        System.out.println("checkZero for " + testCase);
+        testCase.deoptimize();
+        InstalledCode installedCode = testCase.toInstalledCode();
+        String str = CompilerToVMHelper.disassembleCodeBlob(installedCode);
+        Asserts.assertNull(str, testCase
+                + " : non-null return value for invalid installCode");
     }
 
     private void check(CompileCodeTestCase testCase) {
@@ -71,12 +84,13 @@
         if (nMethod == null) {
             throw new Error(testCase + " : method is not compiled");
         }
-        String str = CompilerToVMHelper.disassembleCodeBlob(nMethod.address);
+        InstalledCode installedCode = testCase.toInstalledCode();
+        String str = CompilerToVMHelper.disassembleCodeBlob(installedCode);
         if (str != null) {
             Asserts.assertGT(str.length(), 0,
                    testCase +  " : returned string has to be non-zero length");
         }
-        String str2 = CompilerToVMHelper.disassembleCodeBlob(nMethod.address);
+        String str2 = CompilerToVMHelper.disassembleCodeBlob(installedCode);
         Asserts.assertEQ(str, str2,
                 testCase + " : 2nd invocation returned different value");
     }
--- a/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -45,7 +45,7 @@
 import java.util.Arrays;
 import java.util.List;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.test.lib.Asserts;
 import sun.hotspot.WhiteBox;
 
@@ -59,7 +59,7 @@
     }
 
     private static void runSanityTest(Executable aMethod) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         boolean canInline = CompilerToVMHelper.canInlineMethod(method);
         Asserts.assertTrue(canInline, "Unexpected initial " +
--- a/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -4,6 +4,7 @@
 import jdk.vm.ci.code.InvalidInstalledCodeException;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
 import jdk.test.lib.Pair;
 import sun.hotspot.code.NMethod;
 
@@ -35,7 +36,6 @@
 
 public class ExecuteInstalledCodeTest {
 
-
     public static void main(String[] args) {
         ExecuteInstalledCodeTest test = new ExecuteInstalledCodeTest();
         List<CompileCodeTestCase> testCases = new ArrayList<>();
@@ -54,15 +54,14 @@
         // to have a clean state
         testCase.deoptimize();
         Pair<Object, ? extends Throwable> reflectionResult;
-        Object[] args = getArguments(testCase.executable);
-        reflectionResult = invoke(testCase, args);
+        Object[] args = Utils.getNullValues(
+                testCase.executable.getParameterTypes());
+        reflectionResult = testCase.invoke(args);
         NMethod nMethod = testCase.compile();
         if (nMethod == null) {
             throw new Error(testCase + " : nmethod is null");
         }
-        InstalledCode installedCode = new InstalledCode(
-                testCase.executable.getName());
-        installedCode.setAddress(nMethod.address);
+        InstalledCode installedCode = testCase.toInstalledCode();
         Object result = null;
         Throwable expectedException = reflectionResult.second;
         boolean gotException = true;
@@ -107,70 +106,10 @@
         if (!Modifier.isStatic(testCase.executable.getModifiers())) {
             // add instance as 0th arg
             Object[] newArgs = new Object[args.length + 1];
-            newArgs[0] = getReciever(testCase);
+            newArgs[0] = testCase.receiver;
             System.arraycopy(args, 0, newArgs, 1, args.length);
             args = newArgs;
         }
         return args;
     }
-
-    private Object getReciever(CompileCodeTestCase testCase) {
-        return CompileCodeTestCase.RECEIVERS.get(
-                testCase.executable.getDeclaringClass());
-    }
-
-    public Pair<Object, ? extends Throwable> invoke(
-            CompileCodeTestCase testCase, Object[] args) {
-        Executable executable = testCase.executable;
-        boolean old = executable.isAccessible();
-        executable.setAccessible(true);
-        try {
-            try {
-                if (executable instanceof Method) {
-                    Method m = (Method) executable;
-                    return new Pair<>(m.invoke(getReciever(testCase), args), null);
-                }
-
-                if (executable instanceof Constructor) {
-                    Constructor c = (Constructor) executable;
-                    return new Pair<>(c.newInstance(args), null);
-                }
-            } catch (InvocationTargetException e) {
-                return new Pair<>(null, e.getCause());
-            } catch (Throwable e) {
-                return new Pair<>(null, e);
-            }
-        } finally {
-            executable.setAccessible(old);
-        }
-        throw new Error(executable + " has unsupported type "
-                + executable.getClass());
-    }
-
-    private Object[] getArguments(Executable method) {
-        Class<?>[] params = method.getParameterTypes();
-        Object[] result = new Object[params.length];
-        int i = 0;
-        for (Class<?> aClass : params) {
-            result[i++] = getArgument(aClass);
-        }
-        return result;
-    }
-    private static Map<Class<?>, Object> DEFAULT_VALUES = new HashMap<>();
-    static {
-        DEFAULT_VALUES.put(boolean.class, false);
-        DEFAULT_VALUES.put(byte.class, (byte) 0);
-        DEFAULT_VALUES.put(short.class, (short) 0);
-        DEFAULT_VALUES.put(char.class, '\0');
-        DEFAULT_VALUES.put(int.class, 0);
-        DEFAULT_VALUES.put(long.class, 0L);
-        DEFAULT_VALUES.put(float.class, 0.0f);
-        DEFAULT_VALUES.put(double.class, 0.0d);
-    }
-    private Object getArgument(Class<?> aClass) {
-        if (aClass.isPrimitive()) {
-            return DEFAULT_VALUES.get(aClass);
-        }
-        return null;
-    }
 }
--- a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -45,8 +45,8 @@
 import java.util.HashSet;
 import java.util.Set;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 
@@ -97,26 +97,26 @@
     private void runTest(TestCase tcase) throws NoSuchMethodException {
         System.out.println(tcase);
         Method method = tcase.holder.getDeclaredMethod(tcase.methodName);
-        HotSpotResolvedJavaMethodImpl testMethod = CTVMUtilities
-                .getResolvedMethod(tcase.reciever, method);
-        HotSpotResolvedObjectTypeImpl resolvedType = CompilerToVMHelper
-                .lookupType(Utils.toJVMTypeSignature(tcase.reciever), getClass(),
+        HotSpotResolvedJavaMethod testMethod = CTVMUtilities
+                .getResolvedMethod(tcase.receiver, method);
+        HotSpotResolvedObjectType resolvedType = CompilerToVMHelper
+                .lookupType(Utils.toJVMTypeSignature(tcase.receiver), getClass(),
                 /* resolve = */ true);
-        HotSpotResolvedJavaMethodImpl concreteMethod = CompilerToVMHelper
+        HotSpotResolvedJavaMethod concreteMethod = CompilerToVMHelper
                 .findUniqueConcreteMethod(resolvedType, testMethod);
         Asserts.assertEQ(concreteMethod, tcase.isPositive ? testMethod : null,
                 "Unexpected concrete method for " + tcase.methodName);
     }
 
     private static class TestCase {
-        public final Class<?> reciever;
+        public final Class<?> receiver;
         public final Class<?> holder;
         public final String methodName;
         public final boolean isPositive;
 
         public TestCase(boolean isPositive, Class<?> clazz, Class<?> holder,
                 String methodName) {
-            this.reciever = clazz;
+            this.receiver = clazz;
             this.methodName = methodName;
             this.isPositive = isPositive;
             this.holder = holder;
@@ -124,8 +124,8 @@
 
         @Override
         public String toString() {
-            return String.format("CASE: reciever=%s, holder=%s, method=%s,"
-                    + " isPositive=%s", reciever.getName(),
+            return String.format("CASE: receiver=%s, holder=%s, method=%s,"
+                    + " isPositive=%s", receiver.getName(),
                     holder.getName(), methodName, isPositive);
         }
     }
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -40,7 +40,7 @@
 import compiler.jvmci.common.testcases.TestCase;
 import java.lang.reflect.Executable;
 import java.lang.reflect.Modifier;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.test.lib.Asserts;
@@ -53,7 +53,7 @@
     }
 
     private static void runSanityTest(Executable aMethod) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         byte[] bytecode = CompilerToVMHelper.getBytecode(method);
 
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -44,8 +44,8 @@
 import java.util.HashSet;
 import java.util.Set;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 
@@ -78,10 +78,10 @@
     private void runTest(TestCase tcase) {
         System.out.println(tcase);
         String className = tcase.holder.getName();
-        HotSpotResolvedObjectTypeImpl resolvedClazz = CompilerToVMHelper
+        HotSpotResolvedObjectType resolvedClazz = CompilerToVMHelper
                 .lookupType(Utils.toJVMTypeSignature(tcase.holder),
                         getClass(), /* resolve = */ true);
-        HotSpotResolvedJavaMethodImpl initializer = CompilerToVMHelper
+        HotSpotResolvedJavaMethod initializer = CompilerToVMHelper
                 .getClassInitializer(resolvedClazz);
         if (tcase.isPositive) {
             Asserts.assertNotNull(initializer, "Couldn't get initializer for "
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,12 +27,13 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
  * @library /testlibrary /../../test/lib /
- * @compile ../common/CompilerToVMHelper.java
+ * @compile ../common/CompilerToVMHelper.java ../common/PublicMetaspaceWrapperObject.java
  * @build sun.hotspot.WhiteBox
  *        compiler.jvmci.compilerToVM.GetConstantPoolTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  *                              jdk.vm.ci.hotspot.CompilerToVMHelper
+ *                              jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  *                   -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions
  *                   -XX:+EnableJVMCI compiler.jvmci.compilerToVM.GetConstantPoolTest
@@ -40,11 +41,11 @@
 package compiler.jvmci.compilerToVM;
 
 import java.lang.reflect.Field;
+import jdk.vm.ci.meta.ConstantPool;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotConstantPool;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
-import jdk.vm.ci.hotspot.MetaspaceWrapperObject;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject;
 import jdk.test.lib.Utils;
 import sun.hotspot.WhiteBox;
 import sun.misc.Unsafe;
@@ -56,25 +57,26 @@
     private static enum TestCase {
         NULL_BASE {
             @Override
-            HotSpotConstantPool getConstantPool() {
+            ConstantPool getConstantPool() {
                 return CompilerToVMHelper.getConstantPool(null,
                         getPtrToCpAddress());
             }
         },
         JAVA_METHOD_BASE {
             @Override
-            HotSpotConstantPool getConstantPool() {
-                HotSpotResolvedJavaMethodImpl methodInstance
+            ConstantPool getConstantPool() {
+                HotSpotResolvedJavaMethod methodInstance
                         = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
                                 TEST_CLASS, 0);
                 Field field;
                 try {
-                    field = HotSpotResolvedJavaMethodImpl
-                            .class.getDeclaredField("metaspaceMethod");
+                    // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod
+                    field = methodInstance.getClass()
+                            .getDeclaredField("metaspaceMethod");
                     field.setAccessible(true);
                     field.set(methodInstance, getPtrToCpAddress());
                 } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
+                    throw new Error("TESTBUG : " + e, e);
                 }
 
                 return CompilerToVMHelper.getConstantPool(methodInstance, 0L);
@@ -82,12 +84,12 @@
         },
         CONSTANT_POOL_BASE {
             @Override
-            HotSpotConstantPool getConstantPool() {
-                HotSpotConstantPool cpInst;
+            ConstantPool getConstantPool() {
+                ConstantPool cpInst;
                 try {
                     cpInst = CompilerToVMHelper.getConstantPool(null,
                             getPtrToCpAddress());
-                    Field field = HotSpotConstantPool.class
+                    Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
                             .getDeclaredField("metaspaceConstantPool");
                     field.setAccessible(true);
                     field.set(cpInst, getPtrToCpAddress());
@@ -99,12 +101,12 @@
         },
         CONSTANT_POOL_BASE_IN_TWO {
             @Override
-            HotSpotConstantPool getConstantPool() {
+            ConstantPool getConstantPool() {
                 long ptr = getPtrToCpAddress();
-                HotSpotConstantPool cpInst;
+                ConstantPool cpInst;
                 try {
                     cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
-                    Field field = HotSpotConstantPool.class
+                    Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
                             .getDeclaredField("metaspaceConstantPool");
                     field.setAccessible(true);
                     field.set(cpInst, ptr / 2L);
@@ -117,12 +119,12 @@
         },
         CONSTANT_POOL_BASE_ZERO {
             @Override
-            HotSpotConstantPool getConstantPool() {
+            ConstantPool getConstantPool() {
                 long ptr = getPtrToCpAddress();
-                HotSpotConstantPool cpInst;
+                ConstantPool cpInst;
                 try {
                     cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
-                    Field field = HotSpotConstantPool.class
+                    Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
                             .getDeclaredField("metaspaceConstantPool");
                     field.setAccessible(true);
                     field.set(cpInst, 0L);
@@ -134,9 +136,9 @@
         },
         OBJECT_TYPE_BASE {
             @Override
-            HotSpotConstantPool getConstantPool() {
-                HotSpotResolvedObjectTypeImpl type
-                        = HotSpotResolvedObjectTypeImpl.fromObjectClass(
+            ConstantPool getConstantPool() {
+                HotSpotResolvedObjectType type
+                        = HotSpotResolvedObjectType.fromObjectClass(
                                 OBJECT_TYPE_BASE.getClass());
                 long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE);
                 return CompilerToVMHelper.getConstantPool(type,
@@ -144,26 +146,28 @@
             }
         },
         ;
-        abstract HotSpotConstantPool getConstantPool();
+        abstract ConstantPool getConstantPool();
     }
 
     private static final WhiteBox WB = WhiteBox.getWhiteBox();
     private static final Unsafe UNSAFE = Utils.getUnsafe();
+
     private static final Class TEST_CLASS = GetConstantPoolTest.class;
     private static final long CP_ADDRESS
             = WB.getConstantPool(GetConstantPoolTest.class);
 
     public void test(TestCase testCase) {
         System.out.println(testCase.name());
-        HotSpotConstantPool cp = testCase.getConstantPool();
+        ConstantPool cp = testCase.getConstantPool();
         String cpStringRep = cp.toString();
-        if (!cpStringRep.contains(HotSpotConstantPool.class.getSimpleName())
+        String cpClassSimpleName
+                = CompilerToVMHelper.HotSpotConstantPoolClass().getSimpleName();
+        if (!cpStringRep.contains(cpClassSimpleName)
                 || !cpStringRep.contains(TEST_CLASS.getName())) {
             String msg = String.format("%s : "
                     + " Constant pool is not valid."
                     + " String representation should contain \"%s\" and \"%s\"",
-                    testCase.name(),
-                    HotSpotConstantPool.class.getSimpleName(),
+                    testCase.name(), cpClassSimpleName,
                     TEST_CLASS.getName());
             throw new AssertionError(msg);
         }
@@ -180,8 +184,7 @@
 
     private static void testObjectBase() {
         try {
-            HotSpotConstantPool cp
-                    = CompilerToVMHelper.getConstantPool(new Object(), 0L);
+            Object cp = CompilerToVMHelper.getConstantPool(new Object(), 0L);
             throw new AssertionError("Test OBJECT_BASE."
                 + " Expected IllegalArgumentException has not been caught");
         } catch (IllegalArgumentException iae) {
@@ -190,8 +193,8 @@
     }
     private static void testMetaspaceWrapperBase() {
         try {
-            HotSpotConstantPool cp = CompilerToVMHelper.getConstantPool(
-                    new MetaspaceWrapperObject() {
+            Object cp = CompilerToVMHelper.getConstantPool(
+                    new PublicMetaspaceWrapperObject() {
                         @Override
                         public long getMetaspacePointer() {
                             return getPtrToCpAddress();
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -42,7 +42,7 @@
 import java.net.Socket;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
 
@@ -76,7 +76,7 @@
 
     private static void runSanityTest(Executable aMethod,
                                       Integer expectedTableLength) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         int tableLength = CompilerToVMHelper.getExceptionTableLength(method);
         Asserts.assertEQ(tableLength, expectedTableLength, aMethod
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -51,7 +51,7 @@
 import java.util.Set;
 import java.util.stream.Stream;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 
@@ -98,12 +98,12 @@
 
     private void runTest(TestCase tcase) {
         System.out.println(tcase);
-        HotSpotResolvedObjectTypeImpl resolvedIface = CompilerToVMHelper
+        HotSpotResolvedObjectType resolvedIface = CompilerToVMHelper
                 .lookupType(Utils.toJVMTypeSignature(tcase.anInterface),
                         getClass(), /* resolve = */ true);
-        HotSpotResolvedObjectTypeImpl resolvedImplementer = CompilerToVMHelper
+        HotSpotResolvedObjectType resolvedImplementer = CompilerToVMHelper
                 .getImplementor(resolvedIface);
-        HotSpotResolvedObjectTypeImpl resolvedExpected = null;
+        HotSpotResolvedObjectType resolvedExpected = null;
         if (tcase.expectedImplementer != null) {
             resolvedExpected = CompilerToVMHelper.lookupType(Utils
                     .toJVMTypeSignature(tcase.expectedImplementer),
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -39,7 +39,7 @@
 import compiler.jvmci.common.CTVMUtilities;
 import compiler.jvmci.common.testcases.TestCase;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassVisitor;
 import jdk.internal.org.objectweb.asm.ClassWriter;
@@ -67,7 +67,7 @@
     }
 
     public static void runSanityTest(Executable aMethod) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         long[] lineNumbers = CompilerToVMHelper.getLineNumberTable(method);
         long[] expectedLineNumbers = getExpectedLineNumbers(aMethod);
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -42,7 +42,7 @@
 package compiler.jvmci.compilerToVM;
 
 import compiler.jvmci.common.CTVMUtilities;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
 
@@ -100,7 +100,7 @@
 
     private static void runSanityTest(Executable aMethod,
                                       Integer expectedTableLength) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
 
         int tblLength = CompilerToVMHelper.getLocalVariableTableLength(method);
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -37,20 +37,19 @@
 
 import compiler.jvmci.common.CTVMUtilities;
 import java.lang.reflect.Method;
-import jdk.vm.ci.hotspot.CompilerToVM;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
 import jdk.vm.ci.hotspot.HotSpotStackFrameReference;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.test.lib.Asserts;
 
 public class GetNextStackFrameTest {
     private static final int RECURSION_AMOUNT = 3;
-    private static final HotSpotResolvedJavaMethodImpl REC_FRAME_METHOD;
-    private static final HotSpotResolvedJavaMethodImpl FRAME1_METHOD;
-    private static final HotSpotResolvedJavaMethodImpl FRAME2_METHOD;
-    private static final HotSpotResolvedJavaMethodImpl FRAME3_METHOD;
-    private static final HotSpotResolvedJavaMethodImpl FRAME4_METHOD;
-    private static final HotSpotResolvedJavaMethodImpl RUN_METHOD;
+    private static final ResolvedJavaMethod REC_FRAME_METHOD;
+    private static final ResolvedJavaMethod FRAME1_METHOD;
+    private static final ResolvedJavaMethod FRAME2_METHOD;
+    private static final ResolvedJavaMethod FRAME3_METHOD;
+    private static final ResolvedJavaMethod FRAME4_METHOD;
+    private static final ResolvedJavaMethod RUN_METHOD;
 
     static {
         Method method;
@@ -69,7 +68,7 @@
             method = Thread.class.getDeclaredMethod("run");
             RUN_METHOD = CTVMUtilities.getResolvedMethod(Thread.class, method);
         } catch (NoSuchMethodException e) {
-            throw new Error("TEST BUG: can't find a test method", e);
+            throw new Error("TEST BUG: can't find a test method : " + e, e);
         }
     }
 
@@ -126,7 +125,7 @@
      */
     private void findFirst() {
         checkNextFrameFor(null /* topmost frame */,
-                new HotSpotResolvedJavaMethodImpl[]
+                new ResolvedJavaMethod[]
                         {FRAME2_METHOD, FRAME3_METHOD, FRAME4_METHOD},
                 FRAME4_METHOD, 0);
     }
@@ -139,26 +138,26 @@
         // Check that we would get a frame 4 starting from the topmost frame
         HotSpotStackFrameReference nextStackFrame = checkNextFrameFor(
                 null /* topmost frame */,
-                new HotSpotResolvedJavaMethodImpl[] {FRAME4_METHOD},
+                new ResolvedJavaMethod[] {FRAME4_METHOD},
                 FRAME4_METHOD, 0);
         // Check that we would get a frame 3 starting from frame 4 when we try
         // to search one of the next two frames
         nextStackFrame = checkNextFrameFor(nextStackFrame,
-                new HotSpotResolvedJavaMethodImpl[] {FRAME3_METHOD,
+                new ResolvedJavaMethod[] {FRAME3_METHOD,
                         FRAME2_METHOD},
                 FRAME3_METHOD, 0);
         // Check that we would get a frame 1
         nextStackFrame = checkNextFrameFor(nextStackFrame,
-                new HotSpotResolvedJavaMethodImpl[] {FRAME1_METHOD},
+                new ResolvedJavaMethod[] {FRAME1_METHOD},
                 FRAME1_METHOD, 0);
         // Check that we would skip (RECURSION_AMOUNT - 1) methods and find a
         // recursionFrame starting from frame 1
         nextStackFrame = checkNextFrameFor(nextStackFrame,
-                new HotSpotResolvedJavaMethodImpl[] {REC_FRAME_METHOD},
+                new ResolvedJavaMethod[] {REC_FRAME_METHOD},
                 REC_FRAME_METHOD, RECURSION_AMOUNT - 1);
         // Check that we would get a Thread::run method frame;
         nextStackFrame = checkNextFrameFor(nextStackFrame,
-                new HotSpotResolvedJavaMethodImpl[] {RUN_METHOD},
+                new ResolvedJavaMethod[] {RUN_METHOD},
                 RUN_METHOD, 0);
         // Check that there are no more frames after thread's run method
         nextStackFrame = CompilerToVMHelper.getNextStackFrame(nextStackFrame,
@@ -187,7 +186,7 @@
         // Get frame 4
         HotSpotStackFrameReference nextStackFrame = CompilerToVMHelper
                 .getNextStackFrame(null /* topmost frame */,
-                        new HotSpotResolvedJavaMethodImpl[] {FRAME4_METHOD}, 0);
+                        new ResolvedJavaMethod[] {FRAME4_METHOD}, 0);
         // Get frame 2 by skipping one method starting from frame 4
         checkNextFrameFor(nextStackFrame, null /* any */,
                 FRAME2_METHOD , 1 /* skip one */);
@@ -198,15 +197,18 @@
      */
     private void findYourself() {
         Method method;
+        Class<?> aClass = CompilerToVMHelper.CompilerToVMClass();
         try {
-            method = CompilerToVM.class.getDeclaredMethod("getNextStackFrame",
-                        HotSpotStackFrameReference.class,
-                        HotSpotResolvedJavaMethodImpl[].class, int.class);
+            method = aClass.getDeclaredMethod(
+                    "getNextStackFrame",
+                    HotSpotStackFrameReference.class,
+                    ResolvedJavaMethod[].class,
+                    int.class);
         } catch (NoSuchMethodException e) {
-            throw new Error("TEST BUG: can't find getNextStackFrame method");
+            throw new Error("TEST BUG: can't find getNextStackFrame : " + e, e);
         }
-        HotSpotResolvedJavaMethodImpl self
-                = CTVMUtilities.getResolvedMethod(CompilerToVM.class, method);
+        ResolvedJavaMethod self
+                = CTVMUtilities.getResolvedMethod(aClass, method);
         checkNextFrameFor(null /* topmost frame */, null /* any */, self, 0);
     }
 
@@ -221,8 +223,8 @@
      */
     private HotSpotStackFrameReference checkNextFrameFor(
             HotSpotStackFrameReference currentFrame,
-            HotSpotResolvedJavaMethodImpl[] searchMethods,
-            HotSpotResolvedJavaMethodImpl expected,
+            ResolvedJavaMethod[] searchMethods,
+            ResolvedJavaMethod expected,
             int skip) {
         HotSpotStackFrameReference nextStackFrame = CompilerToVMHelper
                 .getNextStackFrame(currentFrame, searchMethods, skip);
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -36,7 +36,7 @@
 
 package compiler.jvmci.compilerToVM;
 
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
 import java.util.HashMap;
@@ -94,7 +94,7 @@
     }
 
     private static void testSlotBigger(Class<?> holder) {
-        HotSpotResolvedJavaMethodImpl method
+        HotSpotResolvedJavaMethod method
                 = CompilerToVMHelper.getResolvedJavaMethodAtSlot(holder, 50);
         Asserts.assertNull(method, "Got method for non existing slot 50 in "
                 + holder);
@@ -102,10 +102,14 @@
 
     private static void testCorrectMethods(Class<?> holder, int methodsNumber) {
         for (int i = 0; i < methodsNumber; i++) {
-            HotSpotResolvedJavaMethodImpl method = CompilerToVMHelper
+            String caseName = String.format("slot %d in %s",
+                    i, holder.getCanonicalName());
+            HotSpotResolvedJavaMethod method = CompilerToVMHelper
                     .getResolvedJavaMethodAtSlot(holder, i);
-            Asserts.assertNotNull(method, "Did not got method for slot " + i
-                    + " in class " + holder.getCanonicalName());
+            Asserts.assertNotNull(method, caseName + " did not got method");
+            Asserts.assertEQ(holder,
+                    CompilerToVMHelper.getMirror(method.getDeclaringClass()),
+                    caseName + " : unexpected declaring class");
         }
     }
 }
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,11 +27,13 @@
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
  * @library / /testlibrary /../../test/lib
  * @compile ../common/CompilerToVMHelper.java
+ *          ../common/PublicMetaspaceWrapperObject.java
  * @build compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest
  * @run main ClassFileInstaller
  *      sun.hotspot.WhiteBox
  *      sun.hotspot.WhiteBox$WhiteBoxPermission
  *      jdk.vm.ci.hotspot.CompilerToVMHelper
+ *      jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
  *      -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *      compiler.jvmci.compilerToVM.GetResolvedJavaMethodTest
@@ -40,8 +42,8 @@
 package compiler.jvmci.compilerToVM;
 
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
-import jdk.vm.ci.hotspot.MetaspaceWrapperObject;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 import sun.hotspot.WhiteBox;
@@ -53,23 +55,20 @@
     private static enum TestCase {
         NULL_BASE {
             @Override
-            HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() {
+            HotSpotResolvedJavaMethod getResolvedJavaMethod() {
                 return CompilerToVMHelper.getResolvedJavaMethod(
                         null, getPtrToMethod());
             }
         },
         JAVA_METHOD_BASE {
             @Override
-            HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() {
-                HotSpotResolvedJavaMethodImpl methodInstance
+            HotSpotResolvedJavaMethod getResolvedJavaMethod() {
+                HotSpotResolvedJavaMethod methodInstance
                         = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
-                       TEST_CLASS, 0);
-                Field field;
+                                TEST_CLASS, 0);
                 try {
-                    field = HotSpotResolvedJavaMethodImpl
-                            .class.getDeclaredField("metaspaceMethod");
-                    field.setAccessible(true);
-                    field.set(methodInstance, getPtrToMethod());
+                    METASPACE_METHOD_FIELD.set(methodInstance,
+                            getPtrToMethod());
                 } catch (ReflectiveOperationException e) {
                     throw new Error("TEST BUG : " + e, e);
                 }
@@ -79,19 +78,15 @@
         },
         JAVA_METHOD_BASE_IN_TWO {
             @Override
-            HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() {
+            HotSpotResolvedJavaMethod getResolvedJavaMethod() {
                 long ptr = getPtrToMethod();
-                HotSpotResolvedJavaMethodImpl methodInstance
+                HotSpotResolvedJavaMethod methodInstance
                         = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
                         TEST_CLASS, 0);
-                Field field;
                 try {
-                    field = HotSpotResolvedJavaMethodImpl
-                            .class.getDeclaredField("metaspaceMethod");
-                    field.setAccessible(true);
-                    field.set(methodInstance, ptr / 2L);
+                    METASPACE_METHOD_FIELD.set(methodInstance, ptr / 2L);
                 } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
+                    throw new Error("TESTBUG : " + e, e);
                 }
                 return CompilerToVMHelper.getResolvedJavaMethod(methodInstance,
                         ptr - ptr / 2L);
@@ -99,36 +94,42 @@
         },
         JAVA_METHOD_BASE_ZERO {
             @Override
-            HotSpotResolvedJavaMethodImpl getResolvedJavaMethod() {
+            HotSpotResolvedJavaMethod getResolvedJavaMethod() {
                 long ptr = getPtrToMethod();
-                HotSpotResolvedJavaMethodImpl methodInstance
+                HotSpotResolvedJavaMethod methodInstance
                         = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
                         TEST_CLASS, 0);
-                Field field;
                 try {
-                    field = HotSpotResolvedJavaMethodImpl
-                            .class.getDeclaredField("metaspaceMethod");
-                    field.setAccessible(true);
-                    field.set(methodInstance, 0L);
+                    METASPACE_METHOD_FIELD.set(methodInstance, 0L);
                 } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
+                    throw new Error("TESTBUG : " + e, e);
                 }
                 return CompilerToVMHelper.getResolvedJavaMethod(methodInstance,
                         ptr);
             }
         }
         ;
-        abstract HotSpotResolvedJavaMethodImpl getResolvedJavaMethod();
+        abstract HotSpotResolvedJavaMethod getResolvedJavaMethod();
     }
 
     private static final Unsafe UNSAFE = Utils.getUnsafe();
     private static final WhiteBox WB = WhiteBox.getWhiteBox();
+    private static final Field METASPACE_METHOD_FIELD;
     private static final Class<?> TEST_CLASS = GetResolvedJavaMethodTest.class;
     private static final long PTR;
     static  {
-        HotSpotResolvedJavaMethodImpl method
+        HotSpotResolvedJavaMethod method
                 = CompilerToVMHelper.getResolvedJavaMethodAtSlot(TEST_CLASS, 0);
-        PTR = method.getMetaspacePointer();
+        try {
+            // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod
+            METASPACE_METHOD_FIELD = method.getClass()
+                    .getDeclaredField("metaspaceMethod");
+            METASPACE_METHOD_FIELD.setAccessible(true);
+            PTR = (long) METASPACE_METHOD_FIELD.get(method);
+        } catch (ReflectiveOperationException e) {
+            throw new Error("TESTBUG : " + e, e);
+        }
+
     }
 
     private static long getPtrToMethod() {
@@ -144,10 +145,11 @@
 
     public void test(TestCase testCase) {
         System.out.println(testCase.name());
-        HotSpotResolvedJavaMethodImpl result = testCase.getResolvedJavaMethod();
+        HotSpotResolvedJavaMethod result = testCase.getResolvedJavaMethod();
         Asserts.assertNotNull(result, testCase + " : got null");
-        Asserts.assertEQ(result.getDeclaringClass().mirror(), TEST_CLASS,
-                testCase + " : returned method has unexpected declaring class");
+        Asserts.assertEQ(TEST_CLASS,
+                CompilerToVMHelper.getMirror(result.getDeclaringClass()),
+                testCase + " : unexpected declaring class");
     }
 
     public static void main(String[] args) {
@@ -161,9 +163,9 @@
 
     private static void testMetaspaceWrapperBase() {
         try {
-            HotSpotResolvedJavaMethodImpl method
+            HotSpotResolvedJavaMethod method
                     = CompilerToVMHelper.getResolvedJavaMethod(
-                            new MetaspaceWrapperObject() {
+                            new PublicMetaspaceWrapperObject() {
                                 @Override
                                 public long getMetaspacePointer() {
                                     return getPtrToMethod();
@@ -171,18 +173,18 @@
                             }, 0L);
             throw new AssertionError("Test METASPACE_WRAPPER_BASE."
                     + " Expected IllegalArgumentException has not been caught");
-        } catch (IllegalArgumentException iae) {
+        } catch (IllegalArgumentException e) {
             // expected
         }
     }
 
     private static void testObjectBase() {
         try {
-            HotSpotResolvedJavaMethodImpl method
+            HotSpotResolvedJavaMethod method
                     = CompilerToVMHelper.getResolvedJavaMethod(new Object(), 0L);
             throw new AssertionError("Test OBJECT_BASE."
                 + " Expected IllegalArgumentException has not been caught");
-        } catch (IllegalArgumentException iae) {
+        } catch (IllegalArgumentException e) {
             // expected
         }
     }
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,11 +27,13 @@
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
  * @library / /testlibrary /../../test/lib
  * @compile ../common/CompilerToVMHelper.java
+ *          ../common/PublicMetaspaceWrapperObject.java
  * @build compiler.jvmci.compilerToVM.GetResolvedJavaTypeTest
  * @run main ClassFileInstaller
  *      sun.hotspot.WhiteBox
  *      sun.hotspot.WhiteBox$WhiteBoxPermission
  *      jdk.vm.ci.hotspot.CompilerToVMHelper
+ *      jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockExperimentalVMOptions
  *      -XX:+EnableJVMCI -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  *      -XX:+UseCompressedOops
@@ -45,11 +47,11 @@
 package compiler.jvmci.compilerToVM;
 
 import java.lang.reflect.Field;
+import jdk.vm.ci.meta.ConstantPool;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotConstantPool;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
-import jdk.vm.ci.hotspot.MetaspaceWrapperObject;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 import sun.hotspot.WhiteBox;
@@ -59,21 +61,22 @@
     private static enum TestCase {
         NULL_BASE {
             @Override
-            HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+            HotSpotResolvedObjectType getResolvedJavaType() {
                 return CompilerToVMHelper.getResolvedJavaType(
                         null, getPtrToKlass(), COMPRESSED);
             }
         },
         JAVA_METHOD_BASE {
             @Override
-            HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
-                HotSpotResolvedJavaMethodImpl methodInstance
+            HotSpotResolvedObjectType getResolvedJavaType() {
+                HotSpotResolvedJavaMethod methodInstance
                         = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
                         TEST_CLASS, 0);
                 Field field;
                 try {
-                    field = HotSpotResolvedJavaMethodImpl
-                            .class.getDeclaredField("metaspaceMethod");
+                    // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod
+                    field = methodInstance.getClass()
+                            .getDeclaredField("metaspaceMethod");
                     field.setAccessible(true);
                     field.set(methodInstance, getPtrToKlass());
                 } catch (ReflectiveOperationException e) {
@@ -86,17 +89,18 @@
         },
         CONSTANT_POOL_BASE {
             @Override
-            HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
-                HotSpotConstantPool cpInst;
+            HotSpotResolvedObjectType getResolvedJavaType() {
+                ConstantPool cpInst;
                 try {
                     cpInst = CompilerToVMHelper.getConstantPool(null,
                             getPtrToKlass());
-                    Field field = HotSpotConstantPool.class
+                    // jdk.vm.ci.hotspot.HotSpotConstantPool.metaspaceConstantPool
+                    Field field = cpInst.getClass()
                             .getDeclaredField("metaspaceConstantPool");
                     field.setAccessible(true);
                     field.set(cpInst, getPtrToKlass());
                 } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
+                    throw new Error("TESTBUG : " + e, e);
                 }
                 return CompilerToVMHelper.getResolvedJavaType(cpInst,
                         0L, COMPRESSED);
@@ -104,17 +108,18 @@
         },
         CONSTANT_POOL_BASE_IN_TWO {
             @Override
-            HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+            HotSpotResolvedObjectType getResolvedJavaType() {
                 long ptr = getPtrToKlass();
-                HotSpotConstantPool cpInst = HotSpotResolvedObjectTypeImpl
-                        .fromObjectClass(TEST_CLASS).getConstantPool();
+                ConstantPool cpInst = HotSpotResolvedObjectType
+                        .fromObjectClass(TEST_CLASS)
+                        .getConstantPool();
                 try {
-                    Field field = HotSpotConstantPool.class
+                    Field field = cpInst.getClass()
                             .getDeclaredField("metaspaceConstantPool");
                     field.setAccessible(true);
                     field.set(cpInst, ptr / 2L);
                 } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
+                    throw new Error("TESTBUG : " + e, e);
                 }
                 return CompilerToVMHelper.getResolvedJavaType(cpInst,
                         ptr - ptr / 2L, COMPRESSED);
@@ -122,17 +127,18 @@
         },
         CONSTANT_POOL_BASE_ZERO {
             @Override
-            HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
+            HotSpotResolvedObjectType getResolvedJavaType() {
                 long ptr = getPtrToKlass();
-                HotSpotConstantPool cpInst = HotSpotResolvedObjectTypeImpl
-                        .fromObjectClass(TEST_CLASS).getConstantPool();
+                ConstantPool cpInst = HotSpotResolvedObjectType
+                        .fromObjectClass(TEST_CLASS)
+                        .getConstantPool();
                 try {
-                    Field field = HotSpotConstantPool.class
+                    Field field = cpInst.getClass()
                             .getDeclaredField("metaspaceConstantPool");
                     field.setAccessible(true);
                     field.set(cpInst, 0L);
                 } catch (ReflectiveOperationException e) {
-                    throw new Error("TESTBUG : " + e.getMessage(), e);
+                    throw new Error("TESTBUG : " + e, e);
                 }
                 return CompilerToVMHelper.getResolvedJavaType(cpInst,
                         ptr, COMPRESSED);
@@ -140,9 +146,9 @@
         },
         OBJECT_TYPE_BASE {
             @Override
-            HotSpotResolvedObjectTypeImpl getResolvedJavaType() {
-                HotSpotResolvedObjectTypeImpl type
-                        = HotSpotResolvedObjectTypeImpl.fromObjectClass(
+            HotSpotResolvedObjectType getResolvedJavaType() {
+                HotSpotResolvedObjectType type
+                        = HotSpotResolvedObjectType.fromObjectClass(
                         OBJECT_TYPE_BASE.getClass());
                 long ptrToClass = UNSAFE.getKlassPointer(OBJECT_TYPE_BASE);
                 return CompilerToVMHelper.getResolvedJavaType(type,
@@ -150,7 +156,7 @@
             }
         },
         ;
-        abstract HotSpotResolvedObjectTypeImpl getResolvedJavaType();
+        abstract HotSpotResolvedObjectType getResolvedJavaType();
     }
 
     private static final Unsafe UNSAFE = Utils.getUnsafe();
@@ -176,9 +182,10 @@
 
     public void test(TestCase testCase) {
         System.out.println(testCase.name());
-        HotSpotResolvedObjectTypeImpl type = testCase.getResolvedJavaType();
-        Asserts.assertEQ(type.mirror(), TEST_CLASS, testCase +
-                        " Unexpected Class returned by getResolvedJavaType");
+        HotSpotResolvedObjectType type = testCase.getResolvedJavaType();
+        Asserts.assertEQ(TEST_CLASS,
+                CompilerToVMHelper.getMirror(type),
+                testCase +  " : unexpected class returned");
     }
 
     public static void main(String[] args) {
@@ -192,9 +199,9 @@
 
     private static void testMetaspaceWrapperBase() {
         try {
-            HotSpotResolvedObjectTypeImpl type
+            HotSpotResolvedObjectType type
                     = CompilerToVMHelper.getResolvedJavaType(
-                            new MetaspaceWrapperObject() {
+                            new PublicMetaspaceWrapperObject() {
                                 @Override
                                 public long getMetaspacePointer() {
                                     return getPtrToKlass();
@@ -209,7 +216,7 @@
 
     private static void testObjectBase() {
         try {
-            HotSpotResolvedObjectTypeImpl type
+            HotSpotResolvedObjectType type
                     = CompilerToVMHelper.getResolvedJavaType(new Object(), 0L,
                             COMPRESSED);
             throw new AssertionError("Test OBJECT_BASE."
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -41,7 +41,7 @@
 import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
 
@@ -53,7 +53,7 @@
     }
 
     private static void runSanityTest(Executable aMethod, int[] bcis) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         String className = aMethod.getDeclaringClass().getName();
         int lastDot = className.lastIndexOf('.');
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -52,7 +52,7 @@
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.meta.ConstantPool;
 import jdk.test.lib.Utils;
 
@@ -76,7 +76,7 @@
         } catch (NoSuchMethodException e) {
             throw new Error("TEST BUG: can't find test method", e);
         }
-        HotSpotResolvedJavaMethodImpl resolvedMethod
+        HotSpotResolvedJavaMethod resolvedMethod
                 = CTVMUtilities.getResolvedMethod(aClass, method);
         List<String> symbols;
         try {
@@ -101,7 +101,7 @@
         }
     }
 
-    private List<String> getSymbols(HotSpotResolvedJavaMethodImpl
+    private List<String> getSymbols(HotSpotResolvedJavaMethod
             metaspaceMethod) throws ReflectiveOperationException {
         List<String> symbols = new ArrayList<>();
         ConstantPool pool = metaspaceMethod.getConstantPool();
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -53,8 +53,8 @@
 import java.util.Set;
 import java.util.stream.Stream;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 
@@ -125,10 +125,10 @@
     private void runTest(TestCase tcase) throws NoSuchMethodException {
         System.out.println(tcase);
         Method method = tcase.holder.getDeclaredMethod(tcase.methodName);
-        HotSpotResolvedObjectTypeImpl metaspaceKlass = CompilerToVMHelper
+        HotSpotResolvedObjectType metaspaceKlass = CompilerToVMHelper
                 .lookupType(Utils.toJVMTypeSignature(tcase.receiver),
                         getClass(), /* resolve = */ true);
-        HotSpotResolvedJavaMethodImpl metaspaceMethod = CTVMUtilities
+        HotSpotResolvedJavaMethod metaspaceMethod = CTVMUtilities
                 .getResolvedMethod(tcase.holder, method);
         int index = 0;
         try {
--- a/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -43,22 +43,19 @@
 import compiler.jvmci.common.CTVMUtilities;
 
 import java.lang.reflect.Executable;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import compiler.testlibrary.CompilerUtils;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
-import sun.hotspot.WhiteBox;
+import jdk.test.lib.Utils;
 import sun.hotspot.code.NMethod;
 
 public class HasCompiledCodeForOSRTest {
     public static void main(String[] args) {
-        List<CompileCodeTestCase>testCases = createTestCases();
+        List<CompileCodeTestCase> testCases = createTestCases();
         testCases.forEach(HasCompiledCodeForOSRTest::runSanityTest);
     }
 
@@ -67,7 +64,8 @@
 
         try {
             Class<?> aClass = DummyClass.class;
-            testCases.add(new CompileCodeTestCase(
+            Object receiver = new DummyClass();
+            testCases.add(new CompileCodeTestCase(receiver,
                     aClass.getMethod("withLoop"), 17));
         } catch (NoSuchMethodException e) {
             throw new Error("TEST BUG : " + e.getMessage(), e);
@@ -78,8 +76,9 @@
     private static void runSanityTest(CompileCodeTestCase testCase) {
         System.out.println(testCase);
         Executable aMethod = testCase.executable;
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
+        testCase.invoke(Utils.getNullValues(aMethod.getParameterTypes()));
         testCase.deoptimize();
         int[] levels = CompilerUtils.getAvailableCompilationLevels();
         // not compiled
@@ -98,7 +97,9 @@
 
         boolean isCompiled;
         int level = nm.comp_level;
-        for (int i : levels) {
+        int[] someLevels = new int[] {-4, 0, 1, 2, 3, 4, 5, 45};
+        // check levels
+        for (int i : someLevels) {
             isCompiled = CompilerToVMHelper.hasCompiledCodeForOSR(
                     method, testCase.bci, i);
             Asserts.assertEQ(isCompiled, level == i, String.format(
@@ -106,8 +107,20 @@
                             + "level %d", testCase, i));
         }
 
-        for (int i : new int[] {-1, +1}) {
-            int bci = testCase.bci + i;
+        // check bci
+        byte[] bytecode = CompilerToVMHelper.getBytecode(CTVMUtilities
+                .getResolvedMethod(testCase.executable));
+        int[] incorrectBci = new int[] {
+                testCase.bci + 1,
+                testCase.bci - 1,
+                -200,
+                -10,
+                bytecode.length,
+                bytecode.length + 1,
+                bytecode.length + 4,
+                bytecode.length + 200
+        };
+        for (int bci : incorrectBci) {
             isCompiled = CompilerToVMHelper.hasCompiledCodeForOSR(
                     method, bci, level);
             Asserts.assertFalse(isCompiled, String.format(
--- a/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -45,7 +45,7 @@
 import java.util.Set;
 import java.util.stream.Stream;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 
@@ -81,7 +81,7 @@
 
     private void runTest(TestCase tcase) {
         System.out.println(tcase);
-        HotSpotResolvedObjectTypeImpl metaspaceKlass = CompilerToVMHelper
+        HotSpotResolvedObjectType metaspaceKlass = CompilerToVMHelper
                 .lookupType(Utils.toJVMTypeSignature(tcase.aClass),
                         getClass(), /* resolve = */ true);
         Asserts.assertEQ(tcase.expected,
--- a/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -44,6 +44,7 @@
 import java.util.Objects;
 import java.util.function.Consumer;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 import sun.misc.Unsafe;
@@ -72,7 +73,7 @@
 
     private void runTest(List<TestCase> tcases) {
         VMStructDataReader reader = new VMStructDataReader(
-                CompilerToVMHelper.initializeConfiguration());
+                CompilerToVMHelper.initializeConfiguration(HotSpotJVMCIRuntime.runtime().getConfig()));
         while (reader.hasNext()) {
             VMFieldData data = reader.next();
             for (TestCase tcase : tcases) {
--- a/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -41,14 +41,25 @@
 
 package compiler.jvmci.compilerToVM;
 
+import compiler.jvmci.common.CTVMUtilities;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
 import sun.hotspot.code.NMethod;
 
 import java.util.List;
+import jdk.vm.ci.code.CodeCacheProvider;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 
 public class InvalidateInstalledCodeTest {
+    private static final CodeCacheProvider CACHE_PROVIDER
+            = HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend()
+                    .getCodeCache();
+
     public static void main(String[] args) {
         InvalidateInstalledCodeTest test
                 = new InvalidateInstalledCodeTest();
@@ -60,26 +71,37 @@
     }
 
     private void checkNull() {
-        InstalledCode installedCode = new InstalledCode("<null>");
-        installedCode.setAddress(0);
-        CompilerToVMHelper.invalidateInstalledCode(installedCode);
+        Utils.runAndCheckException(
+                () -> CompilerToVMHelper.invalidateInstalledCode(null),
+                NullPointerException.class);
     }
 
     private void check(CompileCodeTestCase testCase) {
         System.out.println(testCase);
-        // to have a clean state
-        NMethod beforeInvalidation = testCase.deoptimizeAndCompile();
-        if (beforeInvalidation == null) {
-            throw new Error("method is not compiled, testCase " + testCase);
+        HotSpotResolvedJavaMethod javaMethod
+                = CTVMUtilities.getResolvedMethod(testCase.executable);
+        HotSpotCompilationRequest compRequest = new HotSpotCompilationRequest(
+                javaMethod, testCase.bci, /* jvmciEnv = */ 0L);
+        String name = testCase.executable.getName();
+        CompilationResult compResult = new CompilationResult(name);
+        // to pass sanity check of default -1
+        compResult.setTotalFrameSize(0);
+        InstalledCode installedCode = CACHE_PROVIDER.installCode(
+                compRequest, compResult,
+                new InstalledCode(name), /* speculationLog = */ null,
+                /* isDefault = */ false);
+        Asserts.assertTrue(installedCode.isValid(), testCase
+                + " : code is invalid even before invalidation");
+
+        NMethod beforeInvalidation = testCase.toNMethod();
+        if (beforeInvalidation != null) {
+            throw new Error("TESTBUG : " + testCase + " : nmethod isn't found");
         }
-
         // run twice to verify how it works if method is already invalidated
         for (int i = 0; i < 2; ++i) {
-            InstalledCode installedCode = new InstalledCode(
-                    testCase.executable.getName());
-            installedCode.setAddress(beforeInvalidation.address);
-
             CompilerToVMHelper.invalidateInstalledCode(installedCode);
+            Asserts.assertFalse(installedCode.isValid(), testCase
+                            + " : code is valid after invalidation, i = " + i);
             NMethod afterInvalidation = testCase.toNMethod();
             if (afterInvalidation != null) {
                 System.err.println("before: " + beforeInvalidation);
@@ -87,8 +109,6 @@
                 throw new AssertionError(testCase
                         + " : method hasn't been invalidated, i = " + i);
             }
-            Asserts.assertFalse(installedCode.isValid(), testCase
-                            + " : code is valid after invalidation, i = " + i);
         }
     }
 }
--- a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  *
  */
 
-/**
+/*
  * @test
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
@@ -40,7 +40,6 @@
 
 package compiler.jvmci.compilerToVM;
 
-import jdk.vm.ci.hotspot.CompilerToVM;
 import jdk.vm.ci.runtime.JVMCI;
 import jdk.test.lib.Asserts;
 
@@ -88,9 +87,12 @@
     private JVM_RegisterJVMCINatives() {
         Method method;
         try {
-            method = CompilerToVM.class.getDeclaredMethod("registerNatives");
+            method = Class.forName("jdk.vm.ci.hotspot.CompilerToVM",
+                    /* initialize = */ false,
+                    this.getClass().getClassLoader())
+                    .getDeclaredMethod("registerNatives");
             method.setAccessible(true);
-        } catch (NoSuchMethodException e) {
+        } catch (ReflectiveOperationException e) {
             throw new Error("can't find CompilerToVM::registerNatives", e);
         }
         registerNatives = method;
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -44,8 +44,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotConstantPool;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import sun.reflect.ConstantPool;
 
 /**
@@ -62,16 +61,16 @@
         testCase.test();
     }
 
-    public static void validate(HotSpotConstantPool constantPoolCTVM,
+    public static void validate(jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
             ConstantPool constantPoolSS,
             ConstantPoolTestsHelper.DummyClasses dummyClass, int i) {
         Object classToVerify = CompilerToVMHelper
                 .lookupKlassInPool(constantPoolCTVM, i);
-        if (!(classToVerify instanceof HotSpotResolvedObjectTypeImpl)
+        if (!(classToVerify instanceof HotSpotResolvedObjectType)
                 && !(classToVerify instanceof String)) {
             String msg = String.format("Output of method"
                     + " CTVM.lookupKlassInPool is neither"
-                    + " a HotSpotResolvedObjectTypeImpl, nor a String");
+                    + " a HotSpotResolvedObjectType, nor a String");
             throw new AssertionError(msg);
         }
         int classNameIndex = (int) dummyClass.cp.get(i).value;
--- a/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -42,7 +42,7 @@
 import java.util.HashSet;
 import java.util.Set;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 
@@ -86,7 +86,7 @@
 
     private void runTest(TestCase tcase) {
         System.out.println(tcase);
-        HotSpotResolvedObjectTypeImpl metaspaceKlass;
+        HotSpotResolvedObjectType metaspaceKlass;
         try {
             metaspaceKlass = CompilerToVMHelper.lookupType(tcase.className,
                     tcase.accessing, tcase.resolve);
--- a/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -46,19 +46,21 @@
 
 package compiler.jvmci.compilerToVM;
 
-import compiler.jvmci.common.CTVMUtilities;
-import compiler.testlibrary.CompilerUtils;
+import java.lang.reflect.Method;
+import jdk.vm.ci.hotspot.HotSpotStackFrameReference;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
+
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.testlibrary.CompilerUtils;
+
 import sun.hotspot.WhiteBox;
-import java.lang.reflect.Method;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
-import jdk.vm.ci.hotspot.HotSpotStackFrameReference;
 
 public class MaterializeVirtualObjectTest {
     private static final WhiteBox WB = WhiteBox.getWhiteBox();
     private static final Method METHOD;
-    private static final HotSpotResolvedJavaMethodImpl RESOLVED_METHOD;
+    private static final ResolvedJavaMethod RESOLVED_METHOD;
     private static final boolean INVALIDATE = Boolean.getBoolean(
             "compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate");
 
@@ -113,7 +115,7 @@
         if (materialize) {
             HotSpotStackFrameReference hsFrame = CompilerToVMHelper
                     .getNextStackFrame(/* topmost frame */ null,
-                            new HotSpotResolvedJavaMethodImpl[]{
+                            new ResolvedJavaMethod[]{
                                 RESOLVED_METHOD}, /* don't skip any */ 0);
             Asserts.assertNotNull(hsFrame, getName() + " : got null frame");
             Asserts.assertTrue(WB.isMethodCompiled(METHOD), getName()
--- a/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -41,7 +41,7 @@
 import java.lang.reflect.Executable;
 import java.util.HashMap;
 import java.util.Map;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.test.lib.Asserts;
 
@@ -54,7 +54,7 @@
     }
 
     private static void runSanityTest(Executable aMethod, Boolean expected) {
-        HotSpotResolvedJavaMethodImpl method
+        HotSpotResolvedJavaMethod method
                 = CTVMUtilities.getResolvedMethod(aMethod);
         boolean isIgnored = CompilerToVMHelper
                 .methodIsIgnoredBySecurityStackWalk(method);
--- a/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -46,7 +46,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
 import jdk.vm.ci.meta.ProfilingInfo;
 import jdk.test.lib.Asserts;
@@ -78,7 +78,7 @@
     }
 
     private static void runSanityTest(Method aMethod) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         ProfilingInfo startProfile = method.getProfilingInfo();
         Asserts.assertFalse(startProfile.isMature(), aMethod
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -42,7 +42,6 @@
 import java.util.HashMap;
 import java.util.Map;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotConstantPool;
 import jdk.test.lib.Asserts;
 import sun.reflect.ConstantPool;
 
@@ -62,7 +61,8 @@
         testCase.test();
     }
 
-    private static void validateMethodHandle(HotSpotConstantPool constantPoolCTVM,
+    private static void validateMethodHandle(
+            jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
             ConstantPool constantPoolSS,
             ConstantPoolTestsHelper.DummyClasses dummyClass, int index) {
         Object constantInPool = CompilerToVMHelper
@@ -77,7 +77,8 @@
         }
     }
 
-    private static void validateMethodType(HotSpotConstantPool constantPoolCTVM,
+    private static void validateMethodType(
+            jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
             ConstantPool constantPoolSS,
             ConstantPoolTestsHelper.DummyClasses dummyClass, int index) {
         Object constantInPool = CompilerToVMHelper
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -49,8 +49,8 @@
 import java.util.HashSet;
 import java.util.Set;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
 import sun.misc.Unsafe;
@@ -125,16 +125,16 @@
 
     private void runTest(TestCase tcase) throws NoSuchMethodException {
         System.out.println(tcase);
-        HotSpotResolvedJavaMethodImpl metaspaceMethod = CTVMUtilities
+        HotSpotResolvedJavaMethod metaspaceMethod = CTVMUtilities
                 .getResolvedMethod(tcase.holder,
                         tcase.holder.getDeclaredMethod(tcase.methodName));
-        HotSpotResolvedObjectTypeImpl holderMetaspace = CompilerToVMHelper
+        HotSpotResolvedObjectType holderMetaspace = CompilerToVMHelper
                 .lookupType(Utils.toJVMTypeSignature(tcase.holder),
                         getClass(), /* resolve = */ true);
-        HotSpotResolvedObjectTypeImpl callerMetaspace = CompilerToVMHelper
+        HotSpotResolvedObjectType callerMetaspace = CompilerToVMHelper
                 .lookupType(Utils.toJVMTypeSignature(tcase.caller),
                         getClass(), /* resolve = */ true);
-        HotSpotResolvedJavaMethodImpl resolvedMetaspaceMethod
+        HotSpotResolvedJavaMethod resolvedMetaspaceMethod
                 = CompilerToVMHelper.resolveMethod(holderMetaspace,
                         metaspaceMethod, callerMetaspace);
         if (tcase.isPositive) {
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -44,8 +44,7 @@
 import java.util.HashMap;
 import java.util.Map;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotConstantPool;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import sun.reflect.ConstantPool;
 
 /**
@@ -62,10 +61,11 @@
         testCase.test();
     }
 
-    public static void validate(HotSpotConstantPool constantPoolCTVM,
+    public static void validate(
+            jdk.vm.ci.meta.ConstantPool constantPoolCTVM,
             ConstantPool constantPoolSS,
             ConstantPoolTestsHelper.DummyClasses dummyClass, int i) {
-        HotSpotResolvedObjectTypeImpl typeToVerify = CompilerToVMHelper
+        HotSpotResolvedObjectType typeToVerify = CompilerToVMHelper
                 .resolveTypeInPool(constantPoolCTVM, i);
         int classNameIndex = (int) dummyClass.cp.get(i).value;
         String classNameToRefer = constantPoolSS.getUTF8At(classNameIndex);
--- a/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -45,7 +45,7 @@
 import java.util.Arrays;
 import java.util.List;
 import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.test.lib.Asserts;
 import sun.hotspot.WhiteBox;
 
@@ -59,7 +59,7 @@
     }
 
     private static void runSanityTest(Executable aMethod) {
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(aMethod);
         boolean shouldInline = CompilerToVMHelper.shouldInlineMethod(method);
         boolean expectedShouldInline = WB.testSetForceInlineMethod(aMethod,
--- a/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.config	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-compiler.jvmci.events.JvmciCompleteInitializationTest
--- a/hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8136421
- * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
- * @library / /testlibrary
- * @build compiler.jvmci.common.JVMCIHelpers
- *     compiler.jvmci.events.JvmciCompleteInitializationTest
- * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/
- * @run main jdk.test.lib.FileInstaller ./JvmciCompleteInitializationTest.config
- *     ./META-INF/services/jdk.vm.ci.hotspot.HotSpotVMEventListener
- * @run main ClassFileInstaller
- *     compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler
- *     compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
- *     compiler.jvmci.events.JvmciCompleteInitializationTest
- *     jdk.test.lib.Asserts
- * @run main/othervm -XX:+UnlockExperimentalVMOptions
- *     -Xbootclasspath/a:.
- *     -XX:+EnableJVMCI
- *     -Dcompiler.jvmci.events.JvmciCompleteInitializationTest.positive=true
- *     compiler.jvmci.events.JvmciCompleteInitializationTest
- * @run main/othervm -XX:+UnlockExperimentalVMOptions
- *     -Xbootclasspath/a:.
- *     -XX:-EnableJVMCI
- *     -Dcompiler.jvmci.events.JvmciCompleteInitializationTest.positive=false
- *     compiler.jvmci.events.JvmciCompleteInitializationTest
- */
-
-package compiler.jvmci.events;
-
-import jdk.test.lib.Asserts;
-import jdk.vm.ci.hotspot.HotSpotVMEventListener;
-import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
-
-public class JvmciCompleteInitializationTest implements HotSpotVMEventListener {
-    private static final boolean IS_POSITIVE = Boolean.getBoolean(
-            "compiler.jvmci.events.JvmciCompleteInitializationTest.positive");
-    private static volatile int completeInitializationCount = 0;
-    private static volatile String errorMessage = "";
-
-    public static void main(String args[]) {
-        if (completeInitializationCount != 0) {
-            throw new Error("Unexpected completeInitialization events"
-                    + " count at start");
-        }
-        initializeRuntime();
-        int expectedEventCount = IS_POSITIVE ? 1 : 0;
-        Asserts.assertEQ(completeInitializationCount, expectedEventCount,
-                "Unexpected completeInitialization events count"
-                        + " after JVMCI init");
-        initializeRuntime();
-        Asserts.assertEQ(completeInitializationCount, expectedEventCount,
-                "Unexpected completeInitialization events count"
-                        + " after 2nd JVMCI init");
-        Asserts.assertTrue(errorMessage.isEmpty(), errorMessage);
-    }
-
-    private static void initializeRuntime() {
-        Error t = null;
-        try {
-            /* in case JVMCI disabled, an InternalError on initialization
-               and NoClassDefFound on 2nd try */
-            HotSpotJVMCIRuntime.runtime();
-        } catch (Error e) {
-            t = e;
-        }
-        if (IS_POSITIVE) {
-            Asserts.assertNull(t, "Caught unexpected exception");
-        } else {
-            Asserts.assertNotNull(t, "Got no expected error");
-        }
-    }
-
-    @Override
-    public void completeInitialization(HotSpotJVMCIRuntime
-            hotSpotJVMCIRuntime) {
-        completeInitializationCount++;
-        if (hotSpotJVMCIRuntime == null) {
-            errorMessage += " HotSpotJVMCIRuntime is null.";
-        }
-    }
-}
--- a/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -61,8 +61,9 @@
 import jdk.vm.ci.code.CompilationResult;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 
 public class JvmciNotifyInstallEventTest implements HotSpotVMEventListener {
     private static final String METHOD_NAME = "testMethod";
@@ -99,17 +100,18 @@
         } catch (NoSuchMethodException e) {
             throw new Error("TEST BUG: Can't find " + METHOD_NAME, e);
         }
-        HotSpotResolvedJavaMethodImpl method = CTVMUtilities
+        HotSpotResolvedJavaMethod method = CTVMUtilities
                 .getResolvedMethod(SimpleClass.class, testMethod);
         CompilationResult compResult = new CompilationResult(METHOD_NAME);
+        HotSpotCompilationRequest compRequest = new HotSpotCompilationRequest(method, -1, 0L);
         // to pass sanity check of default -1
         compResult.setTotalFrameSize(0);
-        codeCache.installMethod(method, compResult, /* jvmciEnv = */ 0L,
+        codeCache.installCode(compRequest, compResult, /* installedCode = */ null, /* speculationLog = */ null,
                 /* isDefault = */ false);
         Asserts.assertEQ(gotInstallNotification, 1,
                 "Got unexpected event count after 1st install attempt");
         // since "empty" compilation result is ok, a second attempt should be ok
-        codeCache.installMethod(method, compResult, /* jvmciEnv = */ 0L,
+        codeCache.installCode(compRequest, compResult, /* installedCode = */ null, /* speculationLog = */ null,
                 /* isDefault = */ false);
         Asserts.assertEQ(gotInstallNotification, 2,
                 "Got unexpected event count after 2nd install attempt");
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/NestedBooleanOptionValueTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/NestedBooleanOptionValueTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,12 +29,20 @@
 
 package jdk.vm.ci.options.test;
 
-import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.*;
-import static org.junit.Assert.*;
-import jdk.vm.ci.options.*;
-import jdk.vm.ci.options.OptionValue.*;
+import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master0;
+import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master1;
+import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.Master2;
+import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption0;
+import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption1;
+import static jdk.vm.ci.options.test.NestedBooleanOptionValueTest.Options.NestedOption2;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import jdk.vm.ci.options.NestedBooleanOptionValue;
+import jdk.vm.ci.options.OptionDescriptor;
+import jdk.vm.ci.options.OptionValue;
+import jdk.vm.ci.options.OptionValue.OverrideScope;
 
-import org.junit.*;
+import org.junit.Test;
 
 public class NestedBooleanOptionValueTest {
 
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/TestOptionValue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/TestOptionValue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,15 +29,21 @@
 
 package jdk.vm.ci.options.test;
 
-import static jdk.vm.ci.options.test.TestOptionValue.Options.*;
-import static org.junit.Assert.*;
-
-import java.util.*;
+import static jdk.vm.ci.options.test.TestOptionValue.Options.Mutable;
+import static jdk.vm.ci.options.test.TestOptionValue.Options.SecondMutable;
+import static jdk.vm.ci.options.test.TestOptionValue.Options.Stable;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
-import jdk.vm.ci.options.*;
-import jdk.vm.ci.options.OptionValue.*;
+import java.util.Arrays;
 
-import org.junit.*;
+import jdk.vm.ci.options.OptionDescriptor;
+import jdk.vm.ci.options.OptionValue;
+import jdk.vm.ci.options.OptionValue.OverrideScope;
+import jdk.vm.ci.options.StableOptionValue;
+
+import org.junit.Test;
 
 @SuppressWarnings("try")
 public class TestOptionValue {
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,9 +30,11 @@
 
 package jdk.vm.ci.runtime.test;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
 
-import org.junit.*;
+import org.junit.Assert;
+import org.junit.Test;
 
 public class ConstantTest extends FieldUniverse {
 
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,11 @@
  */
 package jdk.vm.ci.runtime.test;
 
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ResolvedJavaField;
 
 /**
  * Context for field related tests.
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,10 +22,12 @@
  */
 package jdk.vm.ci.runtime.test;
 
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
  * Context for method related tests.
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,11 +22,14 @@
  */
 package jdk.vm.ci.runtime.test;
 
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.reflect.Method;
+import java.util.Arrays;
 
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.runtime.*;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+import jdk.vm.ci.runtime.JVMCI;
 
 class NameAndSignature {
 
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,22 +30,31 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static org.junit.Assume.*;
+import static org.junit.Assume.assumeTrue;
 
-import java.io.*;
-import java.lang.instrument.*;
-import java.lang.management.*;
-import java.lang.reflect.*;
-import java.nio.file.*;
-import java.security.*;
-import java.util.*;
-import java.util.jar.*;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
 
-import javax.tools.*;
+import javax.tools.ToolProvider;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
-import org.junit.*;
+import org.junit.Assert;
+import org.junit.Test;
 
 /**
  * Tests that {@link ResolvedJavaMethod}s are safe in the context of class redefinition being used
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,11 +29,14 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static org.junit.Assert.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.runtime.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
 
-import org.junit.*;
+import org.junit.Test;
 
 public class ResolvedJavaTypeResolveConcreteMethodTest {
     public final MetaAccessProvider metaAccess;
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,11 +29,14 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static org.junit.Assert.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.runtime.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
 
-import org.junit.*;
+import org.junit.Test;
 
 public class ResolvedJavaTypeResolveMethodTest {
     public final MetaAccessProvider metaAccess;
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,14 +30,20 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.reflect.Array;
+import java.util.List;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
 
-import org.junit.*;
+import org.junit.Test;
 
 /**
  * Tests for {@link ConstantReflectionProvider}. It assumes an implementation of the interface that
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,14 +30,19 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.util.Map;
 
-import java.lang.reflect.*;
-import java.util.*;
+import jdk.vm.ci.meta.JavaField;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
-import jdk.vm.ci.meta.*;
-
-import org.junit.*;
+import org.junit.Test;
 
 /**
  * Tests for {@link JavaField}.
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,14 +30,17 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Method;
+import java.util.Map;
 
-import java.lang.reflect.*;
-import java.util.*;
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
-import jdk.vm.ci.meta.*;
-
-import org.junit.*;
+import org.junit.Test;
 
 /**
  * Tests for {@link JavaMethod}.
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,10 +30,11 @@
 
 package jdk.vm.ci.runtime.test;
 
-import jdk.vm.ci.meta.*;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
 
-import org.junit.*;
+import org.junit.Test;
 
 /**
  * Tests for {@link JavaType}.
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,14 +30,22 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static jdk.vm.ci.meta.MetaUtil.*;
-import static org.junit.Assert.*;
+import static jdk.vm.ci.meta.MetaUtil.toInternalName;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 
-import java.lang.reflect.*;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
-import jdk.vm.ci.meta.*;
-
-import org.junit.*;
+import org.junit.Test;
 
 /**
  * Tests for {@link MetaAccessProvider}.
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,15 +30,27 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.LocationIdentity;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
-import org.junit.*;
+import org.junit.Test;
 
 /**
  * Tests for {@link ResolvedJavaField}.
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,16 +30,35 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
-import java.lang.annotation.*;
-import java.lang.invoke.*;
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
-import jdk.vm.ci.meta.*;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.ExceptionHandler;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
-import org.junit.*;
+import org.junit.Assert;
+import org.junit.Test;
 
 /**
  * Tests for {@link ResolvedJavaMethod}.
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,19 +30,42 @@
 
 package jdk.vm.ci.runtime.test;
 
-import static java.lang.reflect.Modifier.*;
-import static org.junit.Assert.*;
+import static java.lang.reflect.Modifier.isAbstract;
+import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isPrivate;
+import static java.lang.reflect.Modifier.isProtected;
+import static java.lang.reflect.Modifier.isPublic;
+import static java.lang.reflect.Modifier.isStatic;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.net.*;
-import java.util.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
-import jdk.vm.ci.common.*;
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.meta.Assumptions.*;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.Assumptions.AssumptionResult;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ModifiersProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.TrustedInterface;
 
-import org.junit.*;
+import org.junit.Test;
 
 import sun.reflect.ConstantPool;
 
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,20 +22,42 @@
  */
 package jdk.vm.ci.runtime.test;
 
-import static java.lang.reflect.Modifier.*;
+import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isStatic;
 
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.AbstractCollection;
+import java.util.AbstractList;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 import java.util.Queue;
-import java.util.stream.*;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
 
-import jdk.vm.ci.meta.*;
-import jdk.vm.ci.runtime.*;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaField;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.TrustedInterface;
+import jdk.vm.ci.runtime.JVMCI;
 
-import org.junit.*;
+import org.junit.Test;
 
-import sun.misc.*;
+import sun.misc.Unsafe;
 
 //JaCoCo Exclude
 
--- a/hotspot/test/compiler/membars/DekkerTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/membars/DekkerTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,9 +25,9 @@
  * @test
  * @bug 8007898
  * @summary Incorrect optimization of Memory Barriers in Matcher::post_store_load_barrier().
- * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:+StressGCM -XX:+StressLCM DekkerTest
- * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:+StressGCM -XX:+StressLCM DekkerTest
- * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:-TieredCompilation -XX:+StressGCM -XX:+StressLCM DekkerTest
+ * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
+ * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
+ * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
  * @author Martin Doerr martin DOT doerr AT sap DOT com
  *
  * Run 3 times since the failure is intermittent.
--- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java	Wed Jul 05 21:00:20 2017 +0200
@@ -43,13 +43,13 @@
 import jdk.internal.org.objectweb.asm.*;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.Utils;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 
 public class UnsafeGetConstantField {
     static final Class<?> THIS_CLASS = UnsafeGetConstantField.class;
 
-    static final Unsafe U = Utils.getUnsafe();
+    static final Unsafe U = Unsafe.getUnsafe();
 
     public static void main(String[] args) {
         testUnsafeGetAddress();
--- a/hotspot/test/gc/g1/TestGCLogMessages.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/gc/g1/TestGCLogMessages.java	Wed Jul 05 21:00:20 2017 +0200
@@ -79,6 +79,7 @@
         // Misc Top-level
         new LogMessageWithLevel("Code Root Purge", Level.FINER),
         new LogMessageWithLevel("String Dedup Fixup", Level.FINER),
+        new LogMessageWithLevel("Expand Heap After Collection", Level.FINER),
         // Free CSet
         new LogMessageWithLevel("Young Free CSet", Level.FINEST),
         new LogMessageWithLevel("Non-Young Free CSet", Level.FINEST),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Annotations/TestAnnotatedStringEncoding.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+/*
+ * @test
+ * @bug 8054307
+ * @summary Tests the correct encoding of latin1/UTF16 Strings used in annotations.
+ */
+public class TestAnnotatedStringEncoding {
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    @interface Test {
+        String str();
+        int index();
+    }
+
+    public static void main(String[] args) throws Exception {
+        new TestAnnotatedStringEncoding().run();
+    }
+
+    public void run() {
+        // Iterate over annotated methods and retrieve the string
+        for (Method m : this.getClass().getMethods()) {
+            if (m.isAnnotationPresent(Test.class)) {
+                // Check if string equals expected value
+                Test test = m.getAnnotation(Test.class);
+                String str = test.str();
+                int index = test.index();
+                if (!str.equals(strValue[index])) {
+                    throw new RuntimeException(m.getName() + " failed: \"" + str + "\" (0x" + Integer.toHexString(str.charAt(0)) +
+                            ") does not equal \"" + strValue[index] + "\" (0x" + Integer.toHexString(strValue[index].charAt(0)) + ") .");
+                }
+            }
+        }
+        System.out.println("Test passed.");
+    }
+
+    public static String[] strValue = {
+        "\u0000", "\u0020", "\u0021", "\u0080",
+        "\u00FF", "\u0100", "\u017F", "\u01FF",
+        "\u07FF", "\u0800", "\uC280", "\uC2BF",
+        "\uC380", "\uC3BF", "\uC5BF", "\uFFFF",
+        "\u10000", "\u1FFFFF", "\u200000",
+        "\u3FFFFFF", "\u4000000", "\u7FFFFFFF",
+        "ab\uff23\uff24ef\uff27", "\uff21\uff22cd\uff25g", "\u00FF\u00FF\u00FF", "\u00A1\u00A1\u00A1\u00A1", ""};
+
+    @Test(str = "\u0000", index = 0)
+    public static void check0() { }
+
+    @Test(str = "\u0020", index = 1)
+    public static void check1() { }
+
+    @Test(str = "\u0021", index = 2)
+    public static void check2() { }
+
+    @Test(str = "\u0080", index = 3)
+    public static void check3() { }
+
+    @Test(str = "\u00FF", index = 4)
+    public static void check4() { }
+
+    @Test(str = "\u0100", index = 5)
+    public static void check5() { }
+
+    @Test(str = "\u017F", index = 6)
+    public static void check6() { }
+
+    @Test(str = "\u01FF", index = 7)
+    public static void check7() { }
+
+    @Test(str = "\u07FF", index = 8)
+    public static void check8() { }
+
+    @Test(str = "\u0800", index = 9)
+    public static void check9() { }
+
+    @Test(str = "\uC280", index = 10)
+    public static void check10() { }
+
+    @Test(str = "\uC2BF", index = 11)
+    public static void check11() { }
+
+    @Test(str = "\uC380", index = 12)
+    public static void check12() { }
+
+    @Test(str = "\uC3BF", index = 13)
+    public static void check13() { }
+
+    @Test(str = "\uC5BF", index = 14)
+    public static void check14() { }
+
+    @Test(str = "\uFFFF", index = 15)
+    public static void check15() { }
+
+    @Test(str = "\u10000", index = 16)
+    public static void check16() { }
+
+    @Test(str = "\u1FFFFF", index = 17)
+    public static void check17() { }
+
+    @Test(str = "\u200000", index = 18)
+    public static void check18() { }
+
+    @Test(str = "\u3FFFFFF", index = 19)
+    public static void check19() { }
+
+    @Test(str = "\u4000000", index = 20)
+    public static void check20() { }
+
+    @Test(str = "\u7FFFFFFF", index = 21)
+    public static void check21() { }
+
+    @Test(str = "ab\uff23\uff24ef\uff27", index = 22)
+    public static void check22() { }
+
+    @Test(str = "\uff21\uff22cd\uff25g", index = 23)
+    public static void check23() { }
+
+    @Test(str = "\u00FF\u00FF\u00FF", index = 24)
+    public static void check24() { }
+
+    @Test(str = "\u00A1\u00A1\u00A1\u00A1", index = 25)
+    public static void check25() { }
+
+    @Test(str = "", index = 26)
+    public static void check26() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/IgnoreUnrecognizedVMOptions.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.test.lib.*;
+
+/*
+ * @test
+ * @bug 8129855
+ * @summary -XX:+IgnoreUnrecognizedVMOptions should work according to the spec from JDK-8129855
+ *
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ * @run main IgnoreUnrecognizedVMOptions
+ */
+public class IgnoreUnrecognizedVMOptions {
+
+  private static void runJavaAndCheckExitValue(boolean shouldSucceed, String... args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    if (shouldSucceed) {
+      output.shouldHaveExitValue(0);
+    } else {
+      output.shouldHaveExitValue(1);
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    boolean product = !Platform.isDebugBuild();
+
+    /*
+      #1.1 wrong value and non-existing flag:
+                                    exists, invalid value           does not exist
+                                    -XX:MinHeapFreeRatio=notnum     -XX:THIS_FLAG_DOESNT_EXIST
+      -IgnoreUnrecognizedVMOptions               ERR                           ERR
+      +IgnoreUnrecognizedVMOptions               ERR                           OK
+    */
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:MinHeapFreeRatio=notnum", "-version");
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:THIS_FLAG_DOESNT_EXIST", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:MinHeapFreeRatio=notnum", "-version");
+    runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:THIS_FLAG_DOESNT_EXIST", "-version");
+
+    /*
+      #1.2 normal flag with ranges:
+                                      exists, in range                exists, out of range
+                                      -XX:StackRedPages=1             -XX:StackRedPages=0
+      -IgnoreUnrecognizedVMOptions               OK                            ERR
+      +IgnoreUnrecognizedVMOptions               OK                            ERR
+    */
+    runJavaAndCheckExitValue(true, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:StackRedPages=1", "-version");
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:StackRedPages=0", "-version");
+    runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:StackRedPages=1", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:StackRedPages=0", "-version");
+
+    /*
+      #1.3 develop & notproduct flag on debug VM:
+                                      develop & !product_build        notproduct & !product_build
+                                      -XX:+DeoptimizeALot             -XX:+VerifyCodeCache
+      -IgnoreUnrecognizedVMOptions               OK                            OK
+      +IgnoreUnrecognizedVMOptions               OK                            OK
+    */
+    if (!product) {
+      runJavaAndCheckExitValue(true, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:+DeoptimizeALot", "-version");
+      runJavaAndCheckExitValue(true, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:+VerifyCodeCache", "-version");
+      runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+DeoptimizeALot", "-version");
+      runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+VerifyCodeCache", "-version");
+    }
+
+    /*
+      #1.4 develop & notproduct flag on product VM:
+                                    develop & !product_build           notproduct & product_build
+                                    -XX:+DeoptimizeALot                -XX:+VerifyCodeCache
+      -IgnoreUnrecognizedVMOptions               ERR                           ERR
+      +IgnoreUnrecognizedVMOptions               OK                            OK
+    */
+    if (product) {
+      runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:+DeoptimizeALot", "-version");
+      runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:+VerifyCodeCache", "-version");
+      runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+DeoptimizeALot", "-version");
+      runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+VerifyCodeCache", "-version");
+    }
+
+
+    /*
+      #1.5 malformed develop & notproduct flag on debug VM:
+                                  develop & !product_build             notproduct & !product_build
+                                  -XX:DeoptimizeALot                   -XX:VerifyCodeCache
+      -IgnoreUnrecognizedVMOptions               ERR                           ERR
+      +IgnoreUnrecognizedVMOptions               ERR                           ERR
+    */
+    if (!product) {
+      runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:DeoptimizeALot", "-version");
+      runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:VerifyCodeCache", "-version");
+      runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:DeoptimizeALot", "-version");
+      runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:VerifyCodeCache", "-version");
+    }
+
+    /*
+      #1.6 malformed develop & notproduct flag on product VM:
+                                    develop & !product_build           notproduct & product_build
+                                    -XX:DeoptimizeALot                 -XX:VerifyCodeCache
+      -IgnoreUnrecognizedVMOptions               ERR                           ERR
+      +IgnoreUnrecognizedVMOptions               OK                            OK
+    */
+    if (product) {
+      runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:DeoptimizeALot", "-version");
+      runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:VerifyCodeCache", "-version");
+      runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:DeoptimizeALot", "-version");
+      runJavaAndCheckExitValue(true, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:VerifyCodeCache", "-version");
+    }
+
+    /*
+      #1.7 locked flag:
+                                      diagnostic & locked             experimental & locked             commercial & locked
+                                      -XX:-UnlockDiagnosticVMOptions  -XX:-UnlockExperimentalVMOptions  -XX:-UnlockCommercialFeatures
+                                      -XX:+PrintInlining              -XX:+AlwaysSafeConstructors       -XX:+FlightRecorder
+      -IgnoreUnrecognizedVMOptions               ERR                           ERR                                 ERR
+      +IgnoreUnrecognizedVMOptions               ERR                           ERR                                 ERR
+    */
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:+PrintInlining", "-version");
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:+AlwaysSafeConstructors", "-version");
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:+FlightRecorder", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:+PrintInlining", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:+AlwaysSafeConstructors", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:+FlightRecorder", "-version");
+
+    /*
+      #1.8 malformed locked flag:
+                                    diagnostic & locked             experimental & locked             commercial & locked
+                                    -XX:-UnlockDiagnosticVMOptions  -XX:-UnlockExperimentalVMOptions  -XX:-UnlockCommercialFeatures
+                                    -XX:PrintInlining               -XX:AlwaysSafeConstructors        -XX:FlightRecorder
+      -IgnoreUnrecognizedVMOptions               ERR                           ERR                                 ERR
+      +IgnoreUnrecognizedVMOptions               ERR                           ERR                                 ERR
+    */
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:PrintInlining", "-version");
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:AlwaysSafeConstructors", "-version");
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:FlightRecorder", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:PrintInlining", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:AlwaysSafeConstructors", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:FlightRecorder", "-version");
+
+    /*
+      #1.9 malformed unlocked flag:
+                                    diagnostic & locked             experimental & locked             commercial & locked
+                                    -XX:+UnlockDiagnosticVMOptions  -XX:+UnlockExperimentalVMOptions  -XX:+UnlockCommercialFeatures
+                                    -XX:PrintInlining               -XX:AlwaysSafeConstructors        -XX:FlightRecorder
+      -IgnoreUnrecognizedVMOptions               ERR                           ERR                                 ERR
+      +IgnoreUnrecognizedVMOptions               ERR                           ERR                                 ERR
+    */
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:PrintInlining", "-version");
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:AlwaysSafeConstructors", "-version");
+    runJavaAndCheckExitValue(false, "-XX:-IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:FlightRecorder", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockDiagnosticVMOptions", "-XX:PrintInlining", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockExperimentalVMOptions", "-XX:AlwaysSafeConstructors", "-version");
+    runJavaAndCheckExitValue(false, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UnlockCommercialFeatures", "-XX:FlightRecorder", "-version");
+  }
+}
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,7 +29,7 @@
  *          java.management
  *          jdk.attach
  *          jdk.management/sun.tools.attach
- * @run main/othervm/timeout=600 TestOptionsWithRanges
+ * @run main/othervm/timeout=780 TestOptionsWithRanges
  */
 
 import java.util.ArrayList;
@@ -70,6 +70,8 @@
         allOptionsAsMap.remove("G1ConcRefinementThreads");
         allOptionsAsMap.remove("G1RSetRegionEntries");
         allOptionsAsMap.remove("G1RSetSparseRegionEntries");
+        allOptionsAsMap.remove("G1UpdateBufferSize");
+        allOptionsAsMap.remove("InitialBootClassLoaderMetaspaceSize");
 
         /*
          * Remove parameters controlling the code cache. As these
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java	Wed Jul 05 21:00:20 2017 +0200
@@ -116,20 +116,6 @@
     }
 
     /**
-     * Add dependency for option depending on it's type. E.g. run the JVM in
-     * compilation mode for compiler options.
-     *
-     * @param option option
-     * @param type type of the option
-     */
-    private static void addTypeDependency(JVMOption option, String type) {
-        if (type.contains("C1") || type.contains("C2")) {
-            /* Run in compiler mode for compiler flags */
-            option.addPrepend("-Xcomp");
-        }
-    }
-
-    /**
      * Parse JVM Options. Get input from "inputReader". Parse using
      * "-XX:+PrintFlagsRanges" output format.
      *
@@ -214,7 +200,6 @@
             token = token.substring(1, token.indexOf("}"));
 
             if (acceptOrigin.test(token)) {
-                addTypeDependency(option, token);
                 addNameDependency(option);
 
                 allOptions.put(name, option);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/CdsDifferentCompactStrings.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 CdsDifferentCompactStrings
+ * @summary CDS (class data sharing) requires the same -XX:[+-]CompactStrings
+ *          setting between archive creation time and load time.
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ *          java.management
+ */
+
+import jdk.test.lib.*;
+
+public class CdsDifferentCompactStrings {
+    public static void main(String[] args) throws Exception {
+        createAndLoadSharedArchive("+", "-");
+        createAndLoadSharedArchive("-", "+");
+    }
+
+    private static void createAndLoadSharedArchive(String create, String load)
+        throws Exception
+    {
+        String createCompactStringsArgument = "-XX:" + create + "CompactStrings";
+        String loadCompactStringsArgument   = "-XX:" + load   + "CompactStrings";
+
+        String filename = "./CdsDifferentCompactStrings" + create + ".jsa";
+
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:SharedArchiveFile=" + filename,
+            "-Xshare:dump",
+            createCompactStringsArgument);
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldContain("Loading classes to share");
+        output.shouldHaveExitValue(0);
+
+        pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:SharedArchiveFile=" + filename,
+            "-Xshare:on",
+            loadCompactStringsArgument,
+            "-version");
+
+        output = new OutputAnalyzer(pb.start());
+        try {
+            output.shouldContain("The shared archive file's CompactStrings " +
+                "setting .* does not equal the current CompactStrings setting");
+        } catch (RuntimeException e) {
+            output.shouldContain("Unable to use shared archive");
+        }
+        output.shouldHaveExitValue(1);
+    }
+}
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Wed Jul 05 21:00:20 2017 +0200
@@ -41,6 +41,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Random;
 import java.util.function.BooleanSupplier;
@@ -594,5 +596,25 @@
         }
         return result;
     }
+
+    public static Object[] getNullValues(Class<?>... types) {
+        Object[] result = new Object[types.length];
+        int i = 0;
+        for (Class<?> type : types) {
+            result[i++] = NULL_VALUES.get(type);
+        }
+        return result;
+    }
+    private static Map<Class<?>, Object> NULL_VALUES = new HashMap<>();
+    static {
+        NULL_VALUES.put(boolean.class, false);
+        NULL_VALUES.put(byte.class, (byte) 0);
+        NULL_VALUES.put(short.class, (short) 0);
+        NULL_VALUES.put(char.class, '\0');
+        NULL_VALUES.put(int.class, 0);
+        NULL_VALUES.put(long.class, 0L);
+        NULL_VALUES.put(float.class, 0.0f);
+        NULL_VALUES.put(double.class, 0.0d);
+    }
 }
 
--- a/jdk/.hgtags	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/.hgtags	Wed Jul 05 21:00:20 2017 +0200
@@ -334,3 +334,4 @@
 0d0a63b325592607974612f9cfb48590975aa2d6 jdk9-b89
 b433e4dfb830fea60e5187e4580791b62cc362d2 jdk9-b90
 97624df5026a2fb191793697dbd2c604c4d5c66e jdk9-b91
+6a5c99506f44538b879d8635a3979849ed587130 jdk9-b92
--- a/jdk/make/Import.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/Import.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -45,8 +45,16 @@
 #
 # Import hotspot
 #
+
+# Don't import jsig library for static builds
+ifneq ($(STATIC_BUILD), true)
+  JSIG_IMPORT = jsig.*
+else
+  JSIG_IMPORT = 
+endif
+
 HOTSPOT_BASE_IMPORT_FILES := \
-    $(addprefix $(LIBRARY_PREFIX), jvm.* jsig.* jvm_db.* jvm_dtrace.*) \
+    $(addprefix $(LIBRARY_PREFIX), jvm.* $(JSIG_IMPORT) jvm_db.* jvm_dtrace.*) \
     Xusage.txt \
     #
 
@@ -79,32 +87,34 @@
 
 ################################################################################
 
-ifeq ($(OPENJDK_TARGET_OS), macosx)
-  JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \
-      $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
-else
-  JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \
-      $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
-endif
+ifneq ($(STATIC_BUILD), true)
+  ifeq ($(OPENJDK_TARGET_OS), macosx)
+    JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \
+        $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
+  else
+    JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \
+        $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
+  endif
 
-ifneq ($(OPENJDK_TARGET_OS), windows)
-  ifeq ($(JVM_VARIANT_SERVER), true)
-    BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
-    ifneq (, $(JSIG_DEBUGINFO))
-      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+  ifneq ($(OPENJDK_TARGET_OS), windows)
+    ifeq ($(JVM_VARIANT_SERVER), true)
+      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
+      ifneq (, $(JSIG_DEBUGINFO))
+        BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/server/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+      endif
     endif
-  endif
-  ifeq ($(JVM_VARIANT_CLIENT), true)
-    BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
-    ifneq (, $(JSIG_DEBUGINFO))
-      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+    ifeq ($(JVM_VARIANT_CLIENT), true)
+      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
+      ifneq (, $(JSIG_DEBUGINFO))
+        BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+      endif
     endif
-  endif
-  ifneq ($(OPENJDK_TARGET_OS), macosx)
-    ifeq ($(JVM_VARIANT_MINIMAL1), true)
-      BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
-      ifneq (,$(JSIG_DEBUGINFO))
-        BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+    ifneq ($(OPENJDK_TARGET_OS), macosx)
+      ifeq ($(JVM_VARIANT_MINIMAL1), true)
+        BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
+        ifneq (,$(JSIG_DEBUGINFO))
+          BASE_TARGETS += $(BASE_INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+        endif
       endif
     endif
   endif
--- a/jdk/make/data/charsetmapping/DoubleByte-X.java.template	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/data/charsetmapping/DoubleByte-X.java.template	Wed Jul 05 21:00:20 2017 +0200
@@ -50,12 +50,12 @@
 
     public CharsetDecoder newDecoder() {
         initb2c();
-        return new  DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$);
+        return new  DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$, $ASCIICOMPATIBLE$);
     }
 
     public CharsetEncoder newEncoder() {
         initc2b();
-        return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex); 
+        return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex, $ASCIICOMPATIBLE$);
     }
 
     $B2C$
--- a/jdk/make/data/charsetmapping/SingleByte-X.java.template	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/data/charsetmapping/SingleByte-X.java.template	Wed Jul 05 21:00:20 2017 +0200
@@ -48,11 +48,11 @@
     }
 
     public CharsetDecoder newDecoder() {
-        return new SingleByte.Decoder(this, b2c);
+        return new SingleByte.Decoder(this, b2c, $ASCIICOMPATIBLE$);
     }
 
     public CharsetEncoder newEncoder() {
-        return new SingleByte.Encoder(this, c2b, c2bIndex);
+        return new SingleByte.Encoder(this, c2b, c2bIndex, $ASCIICOMPATIBLE$);
     }
 
     private final static String b2cTable = $B2CTABLE$
--- a/jdk/make/gensrc/Gensrc-java.base.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/Gensrc-java.base.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -38,15 +38,15 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,LIST_RESOURCE_BUNDLE, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, LIST_RESOURCE_BUNDLE, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources, \
+    CLASS := ListResourceBundle, \
+))
 
-$(eval $(call SetupCompileProperties,SUN_UTIL, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources)), \
-    sun.util.resources.LocaleNamesBundle))
+$(eval $(call SetupCompileProperties, SUN_UTIL, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources, \
+    CLASS := sun.util.resources.LocaleNamesBundle, \
+))
 
 GENSRC_JAVA_BASE += $(LIST_RESOURCE_BUNDLE) $(SUN_UTIL)
 
--- a/jdk/make/gensrc/Gensrc-java.desktop.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/Gensrc-java.desktop.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -66,11 +66,11 @@
   PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources
 endif
 
-PROP_SRC_FILES := $(filter-out %cursors.properties, \
-    $(filter %.properties, $(call CacheFind, $(PROP_SRC_DIRS))))
-
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(PROP_SRC_FILES), ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(PROP_SRC_DIRS), \
+    EXCLUDE := %cursors.properties, \
+    CLASS := ListResourceBundle, \
+))
 
 GENSRC_JAVA_DESKTOP += $(COMPILE_PROPERTIES)
 
--- a/jdk/make/gensrc/Gensrc-java.logging.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/Gensrc-java.logging.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
 # 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,10 +29,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 TARGETS += $(COMPILE_PROPERTIES)
 
--- a/jdk/make/gensrc/Gensrc-java.management.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/Gensrc-java.management.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -32,10 +32,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 TARGETS += $(COMPILE_PROPERTIES)
 
--- a/jdk/make/gensrc/Gensrc-jdk.dev.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/Gensrc-jdk.dev.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
 # 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,11 +29,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, \
-            $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 TARGETS += $(COMPILE_PROPERTIES)
 
--- a/jdk/make/gensrc/Gensrc-jdk.jartool.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/Gensrc-jdk.jartool.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -29,11 +29,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, \
-            $(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 TARGETS += $(COMPILE_PROPERTIES)
 
--- a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 JAVA_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/com/sun/tools/jdi/JDWP.java
 
 # Both the header and java file are created using the same recipe. By declaring
-# this rule and adding header file to dependencies for java file, both are 
+# this rule and adding header file to dependencies for java file, both are
 # rebuilt if either is missing
 $(HEADER_FILE): $(JDWP_SPEC_FILE) $(BUILD_TOOLS_JDK)
 
@@ -90,10 +90,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources)), \
-    ListResourceBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources, \
+    CLASS := ListResourceBundle, \
+))
 
 GENSRC_JDK_JDI += $(COMPILE_PROPERTIES)
 
--- a/jdk/make/gensrc/Gensrc-jdk.localedata.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/Gensrc-jdk.localedata.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
 # 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,10 +35,10 @@
 
 include GensrcProperties.gmk
 
-$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \
-    $(filter %.properties, \
-        $(call CacheFind, $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources)), \
-    sun.util.resources.LocaleNamesBundle))
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+    SRC_DIRS := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources, \
+    CLASS := sun.util.resources.LocaleNamesBundle, \
+))
 
 # Skip generating zh_HK from zh_TW for this module.
 GENSRC_JDK_LOCALEDATA += $(filter-out %_zh_HK.java, $(COMPILE_PROPERTIES))
--- a/jdk/make/gensrc/GensrcProperties.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/gensrc/GensrcProperties.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -49,30 +49,40 @@
 endef
 
 ################################################################################
-# Creates a rule that runs CompileProperties on a set of properties files.
-# Param 1 - Variable to add targets to, must not contain space
-# Param 2 - Properties files to process
-# Param 3 - The super class for the generated classes
-# Param 4 - Module path root, defaults to $(JDK_TOPDIR)/src
-define SetupCompileProperties
-  $1_SRCS := $2
-  $1_CLASS := $3
-  $1_MODULE_PATH_ROOT := $4
-
+# Setup make rules that runs CompileProperties on a set of properties files.
+#
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name.
+#
+# Remaining parameters are named arguments. These include:
+# SRC_DIRS   Directories containing properties files to process.
+# EXCLUDE   Exclude files matching this pattern.
+# CLASS   The super class for the generated classes.
+# MODULE_PATH_ROOT   Module path root, defaults to $(JDK_TOPDIR)/src.
+SetupCompileProperties = $(NamedParamsMacroTemplate)
+define SetupCompilePropertiesBody
+  # Set default value unless overridden
   ifeq ($$($1_MODULE_PATH_ROOT), )
     $1_MODULE_PATH_ROOT := $(JDK_TOPDIR)/src
   endif
 
+  # Locate all properties files in the given source dirs.
+  $1_SRC_FILES := $$(filter %.properties, $$(call CacheFind, $$($1_SRC_DIRS)))
+
+  ifneq ($$($1_EXCLUDE), )
+    $1_SRC_FILES := $$(filter-out $$($1_EXCLUDE), $$($1_SRC_FILES))
+  endif
+
   # Convert .../src/<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties
   # to .../support/gensrc/<module>/com/sun/tools/javac/resources/javac_zh_CN.java
-  # Strip away prefix and suffix, leaving for example only: 
+  # Strip away prefix and suffix, leaving for example only:
   # "<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN"
   $1_JAVAS := $$(patsubst $$($1_MODULE_PATH_ROOT)/%, \
       $(SUPPORT_OUTPUTDIR)/gensrc/%, \
       $$(patsubst %.properties, %.java, \
       $$(subst /$(OPENJDK_TARGET_OS)/classes,, \
       $$(subst /$(OPENJDK_TARGET_OS_TYPE)/classes,, \
-      $$(subst /share/classes,, $$($1_SRCS))))))
+      $$(subst /share/classes,, $$($1_SRC_FILES))))))
 
   # Generate the package dirs for the to be generated java files. Sort to remove
   # duplicates.
@@ -82,22 +92,22 @@
   # "-compile ...javac_zh_CN.properties ...javac_zh_CN.java java.util.ListResourceBundle"
   # suitable to be fed into the CompileProperties command.
   $1_CMDLINE := $$(subst _SPACE_, $(SPACE), \
-      $$(join $$(addprefix -compile_SPACE_, $$($1_SRCS)), \
+      $$(join $$(addprefix -compile_SPACE_, $$($1_SRC_FILES)), \
       $$(addsuffix _SPACE_$$($1_CLASS), \
       $$(addprefix _SPACE_, $$($1_JAVAS)))))
 
-  $1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.done
+  $1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.marker
   $1_CMDLINE_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.cmdline
 
 # Now setup the rule for the generation of the resource bundles.
-  $$($1_TARGET): $$($1_SRCS) $$($1_JAVAS) $(BUILD_TOOLS_JDK)
+  $$($1_TARGET): $$($1_SRC_FILES) $$($1_JAVAS) $(BUILD_TOOLS_JDK)
 	$(MKDIR) -p $$(@D) $$($1_DIRS)
-	$(ECHO) Compiling $$(words $$($1_SRCS)) properties into resource bundles for $(MODULE)
+	$(ECHO) Compiling $$(words $$($1_SRC_FILES)) properties into resource bundles for $(MODULE)
 	$$(eval $$(call ListPathsSafely, $1_CMDLINE, $$($1_CMDLINE_FILE)))
 	$(TOOL_COMPILEPROPERTIES) -quiet @$$($1_CMDLINE_FILE)
 	$(TOUCH) $$@
 
-  $$($1_JAVAS): $$($1_SRCS)
+  $$($1_JAVAS): $$($1_SRC_FILES)
 
   # Create zh_HK versions of all zh_TW files created above
   $$(eval $$(call SetupCopy-zh_HK,$1_HK,$$(filter %_zh_TW.java, $$($1_JAVAS))))
--- a/jdk/make/launcher/LauncherCommon.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/launcher/LauncherCommon.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -122,8 +122,23 @@
     endif
 
     $1_CFLAGS += -DPACKAGE_PATH='"$(PACKAGE_PATH)"'
-    $1_LDFLAGS += -Wl,-all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a \
+    $1_LDFLAGS += -Wl,-all_load \
         -sectcreate __TEXT __info_plist $(MACOSX_PLIST_DIR)/$$($1_PLIST_FILE)
+    ifeq ($(STATIC_BUILD), true)
+      $1_LDFLAGS += -exported_symbols_list \
+              $(SUPPORT_OUTPUTDIR)/build-static/exported.symbols
+      $1_LIBS += \
+          $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs/java.base -name "*.a") \
+          $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/libdt_socket.a \
+          $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/libjdwp.a \
+          $(SUPPORT_OUTPUTDIR)/native/java.base/$(LIBRARY_PREFIX)fdlibm$(STATIC_LIBRARY_SUFFIX) \
+          -framework CoreFoundation \
+          -framework Foundation \
+          -framework SystemConfiguration \
+          -lstdc++ -liconv
+    else
+      $1_LIBS += $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a
+    endif
     $1_LIBS += -framework Cocoa -framework Security \
         -framework ApplicationServices
   endif
--- a/jdk/make/lib/Awt2dLibraries.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/lib/Awt2dLibraries.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -476,7 +476,7 @@
 ifeq ($(USE_EXTERNAL_LIBJPEG), true)
   LIBJPEG_LIBS := -ljpeg
   BUILD_LIBJAVAJPEG_INCLUDE_FILES := \
-      imageIOJPEG.c \
+      imageioJPEG.c \
       jpegdecoder.c
   BUILD_LIBJAVAJPEG_HEADERS :=
 else
--- a/jdk/make/lib/CoreLibraries.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/lib/CoreLibraries.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -435,10 +435,14 @@
       OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \
       DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
 
-  $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a: $(BUILD_LIBJLI_STATIC)
+  ifeq ($(STATIC_BUILD), true)
+    TARGETS += $(BUILD_LIBJLI_STATIC)
+  else
+    $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a: $(BUILD_LIBJLI_STATIC)
 	$(call install-file)
 
-  TARGETS += $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a
+    TARGETS += $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a
+  endif
 
 else ifeq ($(OPENJDK_TARGET_OS), aix)
   # AIX also requires a static libjli because the compiler doesn't support '-rpath'
--- a/jdk/make/lib/Lib-java.base.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/lib/Lib-java.base.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -33,3 +33,29 @@
 include NetworkingLibraries.gmk
 include NioLibraries.gmk
 include SecurityLibraries.gmk
+
+ifeq ($(STATIC_BUILD), true)
+  JAVA_BASE_EXPORT_SYMBOLS_SRC := \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jli/$(LIBRARY_PREFIX)jli.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)java.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)net.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)nio.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)verify.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)zip.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)jimage.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/server/$(LIBRARY_PREFIX)jvm.symbols \
+      #
+
+  JAVA_BASE_EXPORT_SYMBOL_FILE := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/java.base.symbols
+
+  $(JAVA_BASE_EXPORT_SYMBOL_FILE): $(JAVA_BASE_EXPORT_SYMBOLS_SRC)
+	$(ECHO) $(LOG_INFO) "Generating java.base.symbols file"
+	$(CAT) $^ > $@
+
+  # The individual symbol files is generated when the respective lib is built
+  $(JAVA_BASE_EXPORT_SYMBOLS_SRC): $(BUILD_LIBJLI) $(BUILD_LIBJAVA) \
+      $(BUILD_LIBNET) $(BUILD_LIBNIO) $(BUILD_LIBVERIFY) $(BUILD_LIBZIP) \
+      $(BUILD_LIBJIMAGE)
+
+  TARGETS += $(JAVA_BASE_EXPORT_SYMBOL_FILE)
+endif
--- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -102,3 +102,23 @@
 TARGETS += $(BUILD_LIBJDWP)
 
 ################################################################################
+
+ifeq ($(STATIC_BUILD), true)
+  JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC := \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/$(LIBRARY_PREFIX)dt_socket.symbols \
+      $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/$(LIBRARY_PREFIX)jdwp.symbols
+
+  JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE := $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/jdk.jdwp.agent.symbols
+
+  $(JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE): $(JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC)
+	$(ECHO) $(LOG_INFO) "Generating jdk.jdwp.agent symbols file"
+	$(CAT) $^ > $@
+
+  # The individual symbol files is generated when the respective lib is built
+  $(JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC): $(BUILD_LIBDT_SOCKET) $(BUILD_LIBJDWP)
+
+  TARGETS += $(JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE)
+
+endif
+
+################################################################################
--- a/jdk/make/lib/SecurityLibraries.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/lib/SecurityLibraries.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -26,38 +26,41 @@
 include LibCommon.gmk
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
+  # JavaNativeFoundation framework not supported in static builds 
+  ifneq ($(STATIC_BUILD), true)
 
   ################################################################################
 
-  LIBOSXSECURITY_DIRS := $(JDK_TOPDIR)/src/java.base/macosx/native/libosxsecurity
-  LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \
-      $(LIBJAVA_HEADER_FLAGS) \
-      -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
+    LIBOSXSECURITY_DIRS := $(JDK_TOPDIR)/src/java.base/macosx/native/libosxsecurity
+    LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \
+        $(LIBJAVA_HEADER_FLAGS) \
+        -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
 
-  $(eval $(call SetupNativeCompilation,BUILD_LIBOSXSECURITY, \
-      LIBRARY := osxsecurity, \
-      OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-      SRC := $(LIBOSXSECURITY_DIRS), \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(CFLAGS_JDKLIB) \
-          $(LIBOSXSECURITY_CFLAGS), \
-      DISABLED_WARNINGS_clang := deprecated-declarations, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) \
-          -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \
-          $(call SET_SHARED_LIBRARY_ORIGIN) \
-          -fobjc-link-runtime, \
-      LIBS := \
-          -framework JavaNativeFoundation \
-          -framework CoreServices \
-          -framework Security \
-          $(JDKLIB_LIBS), \
-      OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxsecurity, \
-      DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
+    $(eval $(call SetupNativeCompilation,BUILD_LIBOSXSECURITY, \
+        LIBRARY := osxsecurity, \
+        OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+        SRC := $(LIBOSXSECURITY_DIRS), \
+        OPTIMIZATION := LOW, \
+        CFLAGS := $(CFLAGS_JDKLIB) \
+            $(LIBOSXSECURITY_CFLAGS), \
+        DISABLED_WARNINGS_clang := deprecated-declarations, \
+        LDFLAGS := $(LDFLAGS_JDKLIB) \
+            -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \
+            $(call SET_SHARED_LIBRARY_ORIGIN) \
+            -fobjc-link-runtime, \
+        LIBS := \
+            -framework JavaNativeFoundation \
+            -framework CoreServices \
+            -framework Security \
+            $(JDKLIB_LIBS), \
+        OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libosxsecurity, \
+        DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
 
-  $(BUILD_LIBOSXSECURITY): $(BUILD_LIBJAVA)
+    $(BUILD_LIBOSXSECURITY): $(BUILD_LIBJAVA)
 
-  TARGETS += $(BUILD_LIBOSXSECURITY)
+    TARGETS += $(BUILD_LIBOSXSECURITY)
 
   ################################################################################
 
+  endif
 endif
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Wed Jul 05 21:00:20 2017 +0200
@@ -211,6 +211,7 @@
 		Java_java_lang_SecurityManager_getClassContext;
 		Java_java_lang_Shutdown_halt0;
 		Java_java_lang_String_intern;
+		Java_java_lang_StringUTF16_isBigEndian;
 		Java_java_lang_System_identityHashCode;
 		Java_java_lang_System_initProperties;
 		Java_java_lang_System_mapLibraryName;
--- a/jdk/make/mapfiles/libjava/reorder-sparc	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/mapfiles/libjava/reorder-sparc	Wed Jul 05 21:00:20 2017 +0200
@@ -57,6 +57,7 @@
 text: .text%JNU_ClassString;
 text: .text%JNU_CopyObjectArray;
 text: .text%Java_java_lang_String_intern;
+text: .text%Java_java_lang_StringUTF16_isBigEndian;
 text: .text%Java_java_lang_ClassLoader_findLoadedClass0;
 text: .text%Java_java_lang_ClassLoader_findBootstrapClass;
 text: .text%Java_java_lang_Throwable_fillInStackTrace;
--- a/jdk/make/mapfiles/libjava/reorder-sparcv9	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/mapfiles/libjava/reorder-sparcv9	Wed Jul 05 21:00:20 2017 +0200
@@ -29,6 +29,7 @@
 text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
 text: .text%Java_java_lang_Class_forName0;
 text: .text%Java_java_lang_String_intern;
+text: .text%Java_java_lang_StringUTF16_isBigEndian;
 text: .text%Java_java_lang_Float_floatToRawIntBits;
 text: .text%Java_java_lang_Double_doubleToRawLongBits;
 text: .text%Java_java_lang_ClassLoader_findLoadedClass0;
--- a/jdk/make/mapfiles/libjava/reorder-x86	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/mapfiles/libjava/reorder-x86	Wed Jul 05 21:00:20 2017 +0200
@@ -31,6 +31,7 @@
 text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
 text: .text%Java_java_lang_Class_forName0;
 text: .text%Java_java_lang_String_intern;
+text: .text%Java_java_lang_StringUTF16_isBigEndian;
 text: .text%Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
 text: .text%Java_java_lang_Throwable_fillInStackTrace;
 text: .text%Java_java_lang_System_setOut0;
--- a/jdk/make/mapfiles/libnio/mapfile-macosx	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/mapfiles/libnio/mapfile-macosx	Wed Jul 05 21:00:20 2017 +0200
@@ -75,6 +75,7 @@
                 Java_sun_nio_ch_IOUtil_makePipe;
                 Java_sun_nio_ch_IOUtil_randomBytes;
                 Java_sun_nio_ch_IOUtil_setfdVal;
+                Java_sun_nio_ch_IOUtil_iovMax;
 		Java_sun_nio_ch_KQueue_kqueue;
 		Java_sun_nio_ch_KQueue_keventRegister;
 		Java_sun_nio_ch_KQueue_keventPoll;
--- a/jdk/make/src/classes/build/tools/charsetmapping/DBCS.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/src/classes/build/tools/charsetmapping/DBCS.java	Wed Jul 05 21:00:20 2017 +0200
@@ -197,6 +197,7 @@
                        .replace("$B1MAX$"   , "0x" + Integer.toString(b1Max, 16))
                        .replace("$B2MIN$"   , "0x" + Integer.toString(b2Min, 16))
                        .replace("$B2MAX$"   , "0x" + Integer.toString(b2Max, 16))
+                       .replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false")
                        .replace("$B2C$", b2c)
                        .replace("$C2BLENGTH$", "0x" + Integer.toString(c2bOff, 16))
                        .replace("$NONROUNDTRIP_B2C$", b2cNR)
--- a/jdk/make/src/classes/build/tools/charsetmapping/SBCS.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/src/classes/build/tools/charsetmapping/SBCS.java	Wed Jul 05 21:00:20 2017 +0200
@@ -175,6 +175,9 @@
                 else
                     line = "        return (cs instanceof " + clzName + ");";
             }
+            if (line.indexOf("$ASCIICOMPATIBLE$") != -1) {
+                line = line.replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false");
+            }
             if (line.indexOf("$B2CTABLE$") != -1) {
                 line = line.replace("$B2CTABLE$", b2c);
             }
--- a/jdk/make/src/classes/build/tools/x11wrappergen/WrapperGenerator.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/make/src/classes/build/tools/x11wrappergen/WrapperGenerator.java	Wed Jul 05 21:00:20 2017 +0200
@@ -841,7 +841,7 @@
                 pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" );
 
                 pw.println("package "+package_name+";\n");
-                pw.println("import sun.misc.*;\n");
+                pw.println("import jdk.internal.misc.Unsafe;\n");
                 pw.println("import sun.util.logging.PlatformLogger;");
                 String baseClass = stp.getBaseClass();
                 if (baseClass == null) {
@@ -941,7 +941,7 @@
             pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" );
 
             pw.println("package "+package_name+";\n");
-            pw.println("import sun.misc.Unsafe;\n");
+            pw.println("import jdk.internal.misc.Unsafe;\n");
             pw.println("class " + ft.getName() + " {");
             pw.println("\tprivate static Unsafe unsafe = XlibWrapper.unsafe;");
             pw.println("\tprivate boolean __executed = false;");
--- a/jdk/src/demo/share/jvmti/agent_util/agent_util.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/agent_util/agent_util.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -65,6 +65,51 @@
 void *allocate(jvmtiEnv *jvmti, jint len);
 void  add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name);
 
+#ifdef STATIC_BUILD
+/* Macros for handling declaration of static/dynamic
+ * Agent library Load/Attach/Unload functions
+ *
+ * DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload
+ * generate the appropriate entrypoint names based on static
+ * versus dynamic builds.
+ *
+ * STATIC_BUILD must be defined to build static versions of these libraries.
+ * LIBRARY_NAME must be set to the name of the library for static builds.
+ */
+#define ADD_LIB_NAME3(name, lib) name ## lib
+#define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib)
+#define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME)
+
+#define DEF_Agent_OnLoad \
+ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \
+  return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \
+} \
+jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)
+
+#define DEF_Agent_OnAttach \
+ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \
+  return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \
+} \
+jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)
+
+#define DEF_Agent_OnUnload \
+ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \
+{ \
+  void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \
+  ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \
+} \
+void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)
+
+#else
+#define DEF_Agent_OnLoad Agent_OnLoad
+#define DEF_Agent_OnAttach Agent_OnAttach
+#define DEF_Agent_OnUnload Agent_OnUnload
+#endif
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
--- a/jdk/src/demo/share/jvmti/compiledMethodLoad/compiledMethodLoad.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/compiledMethodLoad/compiledMethodLoad.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -225,7 +225,7 @@
  * event here.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jint                rc;
     jvmtiError          err;
@@ -272,6 +272,6 @@
 
 /* Agent_OnUnload() is called last */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 }
--- a/jdk/src/demo/share/jvmti/gctest/gctest.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/gctest/gctest.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -148,7 +148,7 @@
 
 /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jint                rc;
     jvmtiError          err;
@@ -193,6 +193,6 @@
 
 /* Agent_OnUnload() is called last */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 }
--- a/jdk/src/demo/share/jvmti/heapTracker/heapTracker.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/heapTracker/heapTracker.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -894,7 +894,7 @@
  *   loaded. This is the first code executed.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     static GlobalAgentData data;
     jvmtiEnv              *jvmti;
@@ -1010,7 +1010,7 @@
  *   unloaded. This is the last code executed.
  */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
     /* Skip any cleanup, VM is about to die anyway */
 }
--- a/jdk/src/demo/share/jvmti/heapTracker/heapTracker.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/heapTracker/heapTracker.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,9 +64,4 @@
 
 #include "agent_util.h"
 
-/* Agent library externals to export. */
-
-JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
-JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
-
 #endif
--- a/jdk/src/demo/share/jvmti/heapViewer/heapViewer.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/heapViewer/heapViewer.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -235,7 +235,7 @@
 
 /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jint                rc;
     jvmtiError          err;
@@ -283,6 +283,6 @@
 
 /* Agent_OnUnload() is called last */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 }
--- a/jdk/src/demo/share/jvmti/minst/minst.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/minst/minst.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -373,7 +373,7 @@
  *   loaded. This is the first code executed.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     static GlobalAgentData data;
     jvmtiEnv              *jvmti;
@@ -467,7 +467,7 @@
  *   unloaded. This is the last code executed.
  */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
     /* Make sure all malloc/calloc/strdup space is freed */
     if ( gdata->include != NULL ) {
--- a/jdk/src/demo/share/jvmti/minst/minst.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/minst/minst.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,9 +64,4 @@
 
 #include "agent_util.h"
 
-/* Agent library externals to export. */
-
-JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
-JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
-
 #endif
--- a/jdk/src/demo/share/jvmti/mtrace/mtrace.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/mtrace/mtrace.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -697,7 +697,7 @@
  *   loaded. This is the first code executed.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     static GlobalAgentData data;
     jvmtiEnv              *jvmti;
@@ -795,7 +795,7 @@
  *   unloaded. This is the last code executed.
  */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
     /* Make sure all malloc/calloc/strdup space is freed */
     if ( gdata->include != NULL ) {
--- a/jdk/src/demo/share/jvmti/mtrace/mtrace.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/mtrace/mtrace.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,9 +64,4 @@
 
 #include "agent_util.h"
 
-/* Agent library externals to export. */
-
-JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
-JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
-
 #endif
--- a/jdk/src/demo/share/jvmti/versionCheck/versionCheck.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/versionCheck/versionCheck.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -89,7 +89,7 @@
 
 /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jint                rc;
     jvmtiError          err;
@@ -116,6 +116,6 @@
 
 /* Agent_OnUnload() is called last */
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 }
--- a/jdk/src/demo/share/jvmti/waiters/Monitor.hpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/waiters/Monitor.hpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,6 +37,10 @@
  * this sample code.
  */
 
+#ifdef STATIC_BUILD
+#define Monitor WaiterMonitor
+#endif
+
 
 /* C++ Monitor class */
 
--- a/jdk/src/demo/share/jvmti/waiters/Thread.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/waiters/Thread.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -37,6 +37,9 @@
  * this sample code.
  */
 
+#ifdef STATIC_BUILD
+#define Thread WaiterThread
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
--- a/jdk/src/demo/share/jvmti/waiters/waiters.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/demo/share/jvmti/waiters/waiters.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -243,7 +243,7 @@
 
     /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
     JNIEXPORT jint JNICALL
-    Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+    DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
     {
         jvmtiEnv           *jvmti;
         jint                rc;
@@ -288,7 +288,7 @@
 
     /* Agent_OnUnload() is called last */
     JNIEXPORT void JNICALL
-    Agent_OnUnload(JavaVM *vm)
+    DEF_Agent_OnUnload(JavaVM *vm)
     {
     }
 
--- a/jdk/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/aix/classes/sun/nio/ch/AixPollPort.java	Wed Jul 05 21:00:20 2017 +0200
@@ -34,7 +34,7 @@
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * AsynchronousChannelGroup implementation based on the AIX pollset framework.
--- a/jdk/src/java.base/linux/classes/sun/nio/ch/EPoll.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/linux/classes/sun/nio/ch/EPoll.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,7 +26,7 @@
 package sun.nio.ch;
 
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Provides access to the Linux epoll facility.
--- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,7 +29,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.UnixNativeDispatcher.*;
 import static sun.nio.fs.UnixConstants.*;
--- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,7 +29,7 @@
 import java.nio.ByteBuffer;
 import java.io.IOException;
 import java.util.*;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.UnixConstants.*;
 import static sun.nio.fs.LinuxNativeDispatcher.*;
--- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,7 +30,7 @@
 import java.security.PrivilegedAction;
 import java.util.*;
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.UnixNativeDispatcher.*;
 import static sun.nio.fs.UnixConstants.*;
--- a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,7 +26,7 @@
 package sun.nio.ch;
 
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Provides access to the BSD kqueue facility.
--- a/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,13 +35,15 @@
 
 #include "java_props_macosx.h"
 
-
 // need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded
 static void *getJRSFramework() {
     static void *jrsFwk = NULL;
+#ifndef STATIC_BUILD
+// JavaRuntimeSupport doesn't support static Java runtimes
     if (jrsFwk == NULL) {
        jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL);
     }
+#endif
     return jrsFwk;
 }
 
--- a/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c	Wed Jul 05 21:00:20 2017 +0200
@@ -245,6 +245,8 @@
     return sExportedJNIFunctions = fxns;
 }
 
+#ifndef STATIC_BUILD
+
 JNIEXPORT jint JNICALL
 JNI_GetDefaultJavaVMInitArgs(void *args) {
     InvocationFunctions *ifn = GetExportedJNIFunctions();
@@ -265,6 +267,7 @@
     if (ifn == NULL) return JNI_ERR;
     return ifn->GetCreatedJavaVMs(vmBuf, bufLen, nVMs);
 }
+#endif
 
 /*
  * Allow JLI-aware launchers to specify a client/server preference
@@ -303,7 +306,12 @@
     objc_registerThreadWithCollector();
 
     if (main_fptr == NULL) {
+#ifdef STATIC_BUILD
+        extern int main(int argc, char **argv);
+        main_fptr = &main;
+#else
         main_fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
+#endif
         if (main_fptr == NULL) {
             JLI_ReportErrorMessageSys("error locating main entrypoint\n");
             exit(1);
@@ -588,6 +596,9 @@
 
     JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
 
+#ifdef STATIC_BUILD
+    return JNI_TRUE;
+#else
     if (stat(jvmpath, &s) == 0) {
         JLI_TraceLauncher("yes.\n");
         return JNI_TRUE;
@@ -595,6 +606,7 @@
         JLI_TraceLauncher("no.\n");
         return JNI_FALSE;
     }
+#endif
 }
 
 /*
@@ -607,10 +619,18 @@
 
     if (GetApplicationHome(path, pathsize)) {
         /* Is JRE co-located with the application? */
+#ifdef STATIC_BUILD
+        char jvm_cfg[MAXPATHLEN];
+        JLI_Snprintf(jvm_cfg, sizeof(jvm_cfg), "%s/lib/jvm.cfg", path);
+        if (access(jvm_cfg, F_OK) == 0) {
+            return JNI_TRUE;
+        }
+#else
         JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path);
         if (access(libjava, F_OK) == 0) {
             return JNI_TRUE;
         }
+#endif
         /* ensure storage for path + /jre + NULL */
         if ((JLI_StrLen(path) + 4 + 1) > (size_t) pathsize) {
             JLI_TraceLauncher("Insufficient space to store JRE path\n");
@@ -629,6 +649,24 @@
     Dl_info selfInfo;
     dladdr(&GetJREPath, &selfInfo);
 
+#ifdef STATIC_BUILD
+    char jvm_cfg[MAXPATHLEN];
+    char *p = NULL;
+    strncpy(jvm_cfg, selfInfo.dli_fname, MAXPATHLEN);
+    p = strrchr(jvm_cfg, '/'); *p = '\0';
+    p = strrchr(jvm_cfg, '/');
+    if (strcmp(p, "/.") == 0) {
+      *p = '\0';
+      p = strrchr(jvm_cfg, '/'); *p = '\0';
+    }
+    else *p = '\0';
+    strncpy(path, jvm_cfg, pathsize);
+    strncat(jvm_cfg, "/lib/jvm.cfg", MAXPATHLEN);
+    if (access(jvm_cfg, F_OK) == 0) {
+      return JNI_TRUE;
+    }
+#endif
+
     char *realPathToSelf = realpath(selfInfo.dli_fname, path);
     if (realPathToSelf != path) {
         return JNI_FALSE;
@@ -664,7 +702,11 @@
 
     JLI_TraceLauncher("JVM path is %s\n", jvmpath);
 
+#ifndef STATIC_BUILD
     libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
+#else
+    libjvm = dlopen(NULL, RTLD_FIRST);
+#endif
     if (libjvm == NULL) {
         JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
         JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
@@ -714,9 +756,14 @@
     char* exec_path = NULL;
     {
         Dl_info dlinfo;
+
+#ifdef STATIC_BUILD
+        void *fptr;
+        fptr = (void *)&SetExecname;
+#else
         int (*fptr)();
-
         fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
+#endif
         if (fptr == NULL) {
             JLI_ReportErrorMessage(DLL_ERROR3, dlerror());
             return JNI_FALSE;
--- a/jdk/src/java.base/share/classes/java/io/File.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/io/File.java	Wed Jul 05 21:00:20 2017 +0200
@@ -2184,10 +2184,10 @@
 
     private static final long PATH_OFFSET;
     private static final long PREFIX_LENGTH_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             PATH_OFFSET = unsafe.objectFieldOffset(
                     File.class.getDeclaredField("path"));
             PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset(
--- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java	Wed Jul 05 21:00:20 2017 +0200
@@ -40,7 +40,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import static java.io.ObjectStreamClass.processQueue;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.reflect.misc.ReflectUtil;
 
 /**
--- a/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java	Wed Jul 05 21:00:20 2017 +0200
@@ -48,7 +48,7 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.reflect.CallerSensitive;
 import sun.reflect.Reflection;
 import sun.reflect.ReflectionFactory;
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java	Wed Jul 05 21:00:20 2017 +0200
@@ -31,6 +31,12 @@
 import java.util.stream.IntStream;
 import java.util.stream.StreamSupport;
 
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.String.UTF16;
+import static java.lang.String.LATIN1;
+import static java.lang.String.checkIndex;
+import static java.lang.String.checkOffset;
+
 /**
  * A mutable sequence of characters.
  * <p>
@@ -51,7 +57,12 @@
     /**
      * The value is used for character storage.
      */
-    char[] value;
+    byte[] value;
+
+    /**
+     * The id of the encoding used to encode the bytes in {@code value}.
+     */
+    byte coder;
 
     /**
      * The count is the number of characters used.
@@ -68,7 +79,13 @@
      * Creates an AbstractStringBuilder of the specified capacity.
      */
     AbstractStringBuilder(int capacity) {
-        value = new char[capacity];
+        if (COMPACT_STRINGS) {
+            value = new byte[capacity];
+            coder = LATIN1;
+        } else {
+            value = StringUTF16.newBytesFor(capacity);
+            coder = UTF16;
+        }
     }
 
     /**
@@ -90,7 +107,7 @@
      * @return  the current capacity
      */
     public int capacity() {
-        return value.length;
+        return value.length >> coder;
     }
 
     /**
@@ -110,8 +127,9 @@
      * @param   minimumCapacity   the minimum desired capacity.
      */
     public void ensureCapacity(int minimumCapacity) {
-        if (minimumCapacity > 0)
+        if (minimumCapacity > 0) {
             ensureCapacityInternal(minimumCapacity);
+        }
     }
 
     /**
@@ -120,24 +138,48 @@
      */
     private void ensureCapacityInternal(int minimumCapacity) {
         // overflow-conscious code
-        if (minimumCapacity - value.length > 0)
+        int capacity = value.length >> coder;
+        if (minimumCapacity - capacity > 0) {
             expandCapacity(minimumCapacity);
+        }
     }
 
     /**
      * This implements the expansion semantics of ensureCapacity with no
      * size check or synchronization.
      */
-    void expandCapacity(int minimumCapacity) {
-        int newCapacity = value.length * 2 + 2;
-        if (newCapacity - minimumCapacity < 0)
+    private void expandCapacity(int minimumCapacity) {
+        int newCapacity = (value.length >> coder) * 2 + 2;
+        if (newCapacity - minimumCapacity < 0) {
             newCapacity = minimumCapacity;
+        }
         if (newCapacity < 0) {
-            if (minimumCapacity < 0) // overflow
+            if (minimumCapacity < 0) {// overflow
                 throw new OutOfMemoryError();
+            }
             newCapacity = Integer.MAX_VALUE;
         }
-        value = Arrays.copyOf(value, newCapacity);
+        if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
+            if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
+                throw new OutOfMemoryError();
+            }
+            newCapacity = StringUTF16.MAX_LENGTH;
+        }
+        this.value = Arrays.copyOf(value, newCapacity << coder);
+    }
+
+    /**
+     * If the coder is "isLatin1", this inflates the internal 8-bit storage
+     * to 16-bit <hi=0, low> pair storage.
+     */
+    private void inflate() {
+        if (!isLatin1()) {
+            return;
+        }
+        byte[] buf = StringUTF16.newBytesFor(value.length);
+        StringLatin1.inflateSB(value, buf, 0, count);
+        this.value = buf;
+        this.coder = UTF16;
     }
 
     /**
@@ -148,8 +190,9 @@
      * returned by a subsequent call to the {@link #capacity()} method.
      */
     public void trimToSize() {
-        if (count < value.length) {
-            value = Arrays.copyOf(value, count);
+        int length = count << coder;
+        if (length < value.length) {
+            value = Arrays.copyOf(value, length);
         }
     }
 
@@ -179,14 +222,17 @@
      *               {@code newLength} argument is negative.
      */
     public void setLength(int newLength) {
-        if (newLength < 0)
+        if (newLength < 0) {
             throw new StringIndexOutOfBoundsException(newLength);
+        }
         ensureCapacityInternal(newLength);
-
         if (count < newLength) {
-            Arrays.fill(value, count, newLength, '\0');
+            if (isLatin1()) {
+                StringLatin1.fillNull(value, count, newLength);
+            } else {
+                StringUTF16.fillNull(value, count, newLength);
+            }
         }
-
         count = newLength;
     }
 
@@ -209,9 +255,11 @@
      */
     @Override
     public char charAt(int index) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
-        return value[index];
+        checkIndex(index, count);
+        if (isLatin1()) {
+            return (char)(value[index] & 0xff);
+        }
+        return StringUTF16.charAt(value, index);
     }
 
     /**
@@ -236,10 +284,11 @@
      *             sequence.
      */
     public int codePointAt(int index) {
-        if ((index < 0) || (index >= count)) {
-            throw new StringIndexOutOfBoundsException(index);
+        checkIndex(index, count);
+        if (isLatin1()) {
+            return value[index] & 0xff;
         }
-        return Character.codePointAtImpl(value, index, count);
+        return StringUTF16.codePointAtSB(value, index, count);
     }
 
     /**
@@ -265,10 +314,13 @@
      */
     public int codePointBefore(int index) {
         int i = index - 1;
-        if ((i < 0) || (i >= count)) {
+        if (i < 0 || i >= count) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return Character.codePointBeforeImpl(value, index, 0);
+        if (isLatin1()) {
+            return value[i] & 0xff;
+        }
+        return StringUTF16.codePointBeforeSB(value, index);
     }
 
     /**
@@ -295,7 +347,10 @@
         if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
+        if (isLatin1()) {
+            return endIndex - beginIndex;
+        }
+        return StringUTF16.codePointCountSB(value, beginIndex, endIndex);
     }
 
     /**
@@ -321,8 +376,8 @@
         if (index < 0 || index > count) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.offsetByCodePointsImpl(value, 0, count,
-                                                index, codePointOffset);
+        return Character.offsetByCodePoints(this,
+                                            index, codePointOffset);
     }
 
     /**
@@ -355,13 +410,14 @@
      */
     public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
     {
-        if (srcBegin < 0)
-            throw new StringIndexOutOfBoundsException(srcBegin);
-        if ((srcEnd < 0) || (srcEnd > count))
-            throw new StringIndexOutOfBoundsException(srcEnd);
-        if (srcBegin > srcEnd)
-            throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
-        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
+        checkRangeSIOOBE(srcBegin, srcEnd, count);  // compatible to old version
+        int n = srcEnd - srcBegin;
+        checkRange(dstBegin, dstBegin + n, dst.length);
+        if (isLatin1()) {
+            StringLatin1.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
+        } else {
+            StringUTF16.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
+        }
     }
 
     /**
@@ -379,9 +435,15 @@
      *             negative or greater than or equal to {@code length()}.
      */
     public void setCharAt(int index, char ch) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
-        value[index] = ch;
+        checkIndex(index, count);
+        if (isLatin1() && StringLatin1.canEncode(ch)) {
+            value[index] = (byte)ch;
+        } else {
+            if (isLatin1()) {
+                inflate();
+            }
+            StringUTF16.putCharSB(value, index, ch);
+        }
     }
 
     /**
@@ -418,35 +480,34 @@
      * @return  a reference to this object.
      */
     public AbstractStringBuilder append(String str) {
-        if (str == null)
+        if (str == null) {
             return appendNull();
+        }
         int len = str.length();
         ensureCapacityInternal(count + len);
-        str.getChars(0, len, value, count);
+        putStringAt(count, str);
         count += len;
         return this;
     }
 
     // Documentation in subclasses because of synchro difference
     public AbstractStringBuilder append(StringBuffer sb) {
-        if (sb == null)
-            return appendNull();
-        int len = sb.length();
-        ensureCapacityInternal(count + len);
-        sb.getChars(0, len, value, count);
-        count += len;
-        return this;
+        return this.append((AbstractStringBuilder)sb);
     }
 
     /**
      * @since 1.8
      */
     AbstractStringBuilder append(AbstractStringBuilder asb) {
-        if (asb == null)
+        if (asb == null) {
             return appendNull();
+        }
         int len = asb.length();
         ensureCapacityInternal(count + len);
-        asb.getChars(0, len, value, count);
+        if (getCoder() != asb.getCoder()) {
+            inflate();
+        }
+        asb.getBytes(value, count, coder);
         count += len;
         return this;
     }
@@ -454,25 +515,35 @@
     // Documentation in subclasses because of synchro difference
     @Override
     public AbstractStringBuilder append(CharSequence s) {
-        if (s == null)
+        if (s == null) {
             return appendNull();
-        if (s instanceof String)
+        }
+        if (s instanceof String) {
             return this.append((String)s);
-        if (s instanceof AbstractStringBuilder)
+        }
+        if (s instanceof AbstractStringBuilder) {
             return this.append((AbstractStringBuilder)s);
-
+        }
         return this.append(s, 0, s.length());
     }
 
     private AbstractStringBuilder appendNull() {
-        int c = count;
-        ensureCapacityInternal(c + 4);
-        final char[] value = this.value;
-        value[c++] = 'n';
-        value[c++] = 'u';
-        value[c++] = 'l';
-        value[c++] = 'l';
-        count = c;
+        ensureCapacityInternal(count + 4);
+        int count = this.count;
+        byte[] val = this.value;
+        if (isLatin1()) {
+            val[count++] = 'n';
+            val[count++] = 'u';
+            val[count++] = 'l';
+            val[count++] = 'l';
+        } else {
+            checkOffset(count + 4, val.length >> 1);
+            StringUTF16.putChar(val, count++, 'n');
+            StringUTF16.putChar(val, count++, 'u');
+            StringUTF16.putChar(val, count++, 'l');
+            StringUTF16.putChar(val, count++, 'l');
+        }
+        this.count = count;
         return this;
     }
 
@@ -507,21 +578,13 @@
      */
     @Override
     public AbstractStringBuilder append(CharSequence s, int start, int end) {
-        if (s == null)
+        if (s == null) {
             s = "null";
-        if ((start < 0) || (start > end) || (end > s.length()))
-            throw new IndexOutOfBoundsException(
-                "start " + start + ", end " + end + ", s.length() "
-                + s.length());
+        }
+        checkRange(start, end, s.length());
         int len = end - start;
         ensureCapacityInternal(count + len);
-        if (s instanceof String) {
-            ((String)s).getChars(start, end, value, count);
-        } else {
-            for (int i = start, j = count; i < end; i++, j++)
-                value[j] = s.charAt(i);
-        }
-        count += len;
+        appendChars(s, start, end);
         return this;
     }
 
@@ -544,8 +607,7 @@
     public AbstractStringBuilder append(char[] str) {
         int len = str.length;
         ensureCapacityInternal(count + len);
-        System.arraycopy(str, 0, value, count, len);
-        count += len;
+        appendChars(str, 0, len);
         return this;
     }
 
@@ -572,10 +634,10 @@
      *         or {@code offset+len > str.length}
      */
     public AbstractStringBuilder append(char str[], int offset, int len) {
-        if (len > 0)                // let arraycopy report AIOOBE for len < 0
-            ensureCapacityInternal(count + len);
-        System.arraycopy(str, offset, value, count, len);
-        count += len;
+        int end = offset + len;
+        checkRange(offset, end, str.length);
+        ensureCapacityInternal(count + len);
+        appendChars(str, offset, end);
         return this;
     }
 
@@ -592,20 +654,39 @@
      * @return  a reference to this object.
      */
     public AbstractStringBuilder append(boolean b) {
-        if (b) {
-            ensureCapacityInternal(count + 4);
-            value[count++] = 't';
-            value[count++] = 'r';
-            value[count++] = 'u';
-            value[count++] = 'e';
+        ensureCapacityInternal(count + (b ? 4 : 5));
+        int count = this.count;
+        byte[] val = this.value;
+        if (isLatin1()) {
+            if (b) {
+                val[count++] = 't';
+                val[count++] = 'r';
+                val[count++] = 'u';
+                val[count++] = 'e';
+            } else {
+                val[count++] = 'f';
+                val[count++] = 'a';
+                val[count++] = 'l';
+                val[count++] = 's';
+                val[count++] = 'e';
+            }
         } else {
-            ensureCapacityInternal(count + 5);
-            value[count++] = 'f';
-            value[count++] = 'a';
-            value[count++] = 'l';
-            value[count++] = 's';
-            value[count++] = 'e';
+            if (b) {
+                checkOffset(count + 4, val.length >> 1);
+                StringUTF16.putChar(val, count++, 't');
+                StringUTF16.putChar(val, count++, 'r');
+                StringUTF16.putChar(val, count++, 'u');
+                StringUTF16.putChar(val, count++, 'e');
+            } else {
+                checkOffset(count + 5, val.length >> 1);
+                StringUTF16.putChar(val, count++, 'f');
+                StringUTF16.putChar(val, count++, 'a');
+                StringUTF16.putChar(val, count++, 'l');
+                StringUTF16.putChar(val, count++, 's');
+                StringUTF16.putChar(val, count++, 'e');
+            }
         }
+        this.count = count;
         return this;
     }
 
@@ -627,7 +708,14 @@
     @Override
     public AbstractStringBuilder append(char c) {
         ensureCapacityInternal(count + 1);
-        value[count++] = c;
+        if (isLatin1() && StringLatin1.canEncode(c)) {
+            value[count++] = (byte)c;
+        } else {
+            if (isLatin1()) {
+                inflate();
+            }
+            StringUTF16.putCharSB(value, count++, c);
+        }
         return this;
     }
 
@@ -652,7 +740,13 @@
                                      : Integer.stringSize(i);
         int spaceNeeded = count + appendedLength;
         ensureCapacityInternal(spaceNeeded);
-        Integer.getChars(i, spaceNeeded, value);
+        if (isLatin1()) {
+            Integer.getChars(i, spaceNeeded, value);
+        } else {
+            byte[] val = this.value;
+            checkOffset(spaceNeeded, val.length >> 1);
+            Integer.getCharsUTF16(i, spaceNeeded, val);
+        }
         count = spaceNeeded;
         return this;
     }
@@ -678,7 +772,13 @@
                                      : Long.stringSize(l);
         int spaceNeeded = count + appendedLength;
         ensureCapacityInternal(spaceNeeded);
-        Long.getChars(l, spaceNeeded, value);
+        if (isLatin1()) {
+            Long.getChars(l, spaceNeeded, value);
+        } else {
+            byte[] val = this.value;
+            checkOffset(spaceNeeded, val.length >> 1);
+            Long.getCharsUTF16(l, spaceNeeded, val);
+        }
         count = spaceNeeded;
         return this;
     }
@@ -732,15 +832,13 @@
      *             greater than {@code end}.
      */
     public AbstractStringBuilder delete(int start, int end) {
-        if (start < 0)
-            throw new StringIndexOutOfBoundsException(start);
-        if (end > count)
+        if (end > count) {
             end = count;
-        if (start > end)
-            throw new StringIndexOutOfBoundsException();
+        }
+        checkRangeSIOOBE(start, end, count);
         int len = end - start;
         if (len > 0) {
-            System.arraycopy(value, start+len, value, start, count-end);
+            shift(end, -len);
             count -= len;
         }
         return this;
@@ -766,20 +864,10 @@
      * {@code codePoint} isn't a valid Unicode code point
      */
     public AbstractStringBuilder appendCodePoint(int codePoint) {
-        final int count = this.count;
-
         if (Character.isBmpCodePoint(codePoint)) {
-            ensureCapacityInternal(count + 1);
-            value[count] = (char) codePoint;
-            this.count = count + 1;
-        } else if (Character.isValidCodePoint(codePoint)) {
-            ensureCapacityInternal(count + 2);
-            Character.toSurrogates(codePoint, value, count);
-            this.count = count + 2;
-        } else {
-            throw new IllegalArgumentException();
+            return append((char)codePoint);
         }
-        return this;
+        return append(Character.toChars(codePoint));
     }
 
     /**
@@ -800,9 +888,8 @@
      *              {@code length()}.
      */
     public AbstractStringBuilder deleteCharAt(int index) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
-        System.arraycopy(value, index+1, value, index, count-index-1);
+        checkIndex(index, count);
+        shift(index + 1, -1);
         count--;
         return this;
     }
@@ -827,22 +914,16 @@
      *             greater than {@code end}.
      */
     public AbstractStringBuilder replace(int start, int end, String str) {
-        if (start < 0)
-            throw new StringIndexOutOfBoundsException(start);
-        if (start > count)
-            throw new StringIndexOutOfBoundsException("start > length()");
-        if (start > end)
-            throw new StringIndexOutOfBoundsException("start > end");
-
-        if (end > count)
+        if (end > count) {
             end = count;
+        }
+        checkRangeSIOOBE(start, end, count);
         int len = str.length();
         int newCount = count + len - (end - start);
         ensureCapacityInternal(newCount);
-
-        System.arraycopy(value, end, value, start + len, count - end);
-        str.getChars(value, start);
+        shift(end, newCount - count);
         count = newCount;
+        putStringAt(start, str);
         return this;
     }
 
@@ -907,13 +988,16 @@
      *             greater than {@code end}.
      */
     public String substring(int start, int end) {
-        if (start < 0)
-            throw new StringIndexOutOfBoundsException(start);
-        if (end > count)
-            throw new StringIndexOutOfBoundsException(end);
-        if (start > end)
-            throw new StringIndexOutOfBoundsException(end - start);
-        return new String(value, start, end - start);
+        checkRangeSIOOBE(start, end, count);
+        if (isLatin1()) {
+            return StringLatin1.newString(value, start, end - start);
+        }
+        return StringUTF16.newStringSB(value, start, end - start);
+    }
+
+    private void shift(int offset, int n) {
+        System.arraycopy(value, offset << coder,
+                         value, (offset + n) << coder, (count - offset) << coder);
     }
 
     /**
@@ -940,16 +1024,12 @@
     public AbstractStringBuilder insert(int index, char[] str, int offset,
                                         int len)
     {
-        if ((index < 0) || (index > length()))
-            throw new StringIndexOutOfBoundsException(index);
-        if ((offset < 0) || (len < 0) || (offset > str.length - len))
-            throw new StringIndexOutOfBoundsException(
-                "offset " + offset + ", len " + len + ", str.length "
-                + str.length);
+        checkOffset(index, count);
+        checkRangeSIOOBE(offset, offset + len, str.length);
         ensureCapacityInternal(count + len);
-        System.arraycopy(value, index, value, index + len, count - index);
-        System.arraycopy(str, offset, value, index, len);
+        shift(index, len);
         count += len;
+        putCharsAt(index, str, offset, offset + len);
         return this;
     }
 
@@ -1008,15 +1088,15 @@
      * @throws     StringIndexOutOfBoundsException  if the offset is invalid.
      */
     public AbstractStringBuilder insert(int offset, String str) {
-        if ((offset < 0) || (offset > length()))
-            throw new StringIndexOutOfBoundsException(offset);
-        if (str == null)
+        checkOffset(offset, count);
+        if (str == null) {
             str = "null";
+        }
         int len = str.length();
         ensureCapacityInternal(count + len);
-        System.arraycopy(value, offset, value, offset + len, count - offset);
-        str.getChars(value, offset);
+        shift(offset, len);
         count += len;
+        putStringAt(offset, str);
         return this;
     }
 
@@ -1045,13 +1125,12 @@
      * @throws     StringIndexOutOfBoundsException  if the offset is invalid.
      */
     public AbstractStringBuilder insert(int offset, char[] str) {
-        if ((offset < 0) || (offset > length()))
-            throw new StringIndexOutOfBoundsException(offset);
+        checkOffset(offset, count);
         int len = str.length;
         ensureCapacityInternal(count + len);
-        System.arraycopy(value, offset, value, offset + len, count - offset);
-        System.arraycopy(str, 0, value, offset, len);
+        shift(offset, len);
         count += len;
+        putCharsAt(offset, str, 0, len);
         return this;
     }
 
@@ -1077,10 +1156,12 @@
      * @throws     IndexOutOfBoundsException  if the offset is invalid.
      */
     public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
-        if (s == null)
+        if (s == null) {
             s = "null";
-        if (s instanceof String)
+        }
+        if (s instanceof String) {
             return this.insert(dstOffset, (String)s);
+        }
         return this.insert(dstOffset, s, 0, s.length());
     }
 
@@ -1128,23 +1209,19 @@
      *              {@code start} is greater than {@code end} or
      *              {@code end} is greater than {@code s.length()}
      */
-     public AbstractStringBuilder insert(int dstOffset, CharSequence s,
-                                         int start, int end) {
-        if (s == null)
+    public AbstractStringBuilder insert(int dstOffset, CharSequence s,
+                                        int start, int end)
+    {
+        if (s == null) {
             s = "null";
-        if ((dstOffset < 0) || (dstOffset > this.length()))
-            throw new IndexOutOfBoundsException("dstOffset "+dstOffset);
-        if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
-            throw new IndexOutOfBoundsException(
-                "start " + start + ", end " + end + ", s.length() "
-                + s.length());
+        }
+        checkOffset(dstOffset, count);
+        checkRange(start, end, s.length());
         int len = end - start;
         ensureCapacityInternal(count + len);
-        System.arraycopy(value, dstOffset, value, dstOffset + len,
-                         count - dstOffset);
-        for (int i=start; i<end; i++)
-            value[dstOffset++] = s.charAt(i);
+        shift(dstOffset, len);
         count += len;
+        putCharsAt(dstOffset, s, start, end);
         return this;
     }
 
@@ -1191,10 +1268,18 @@
      * @throws     IndexOutOfBoundsException  if the offset is invalid.
      */
     public AbstractStringBuilder insert(int offset, char c) {
+        checkOffset(offset, count);
         ensureCapacityInternal(count + 1);
-        System.arraycopy(value, offset, value, offset + 1, count - offset);
-        value[offset] = c;
+        shift(offset, 1);
         count += 1;
+        if (isLatin1() && StringLatin1.canEncode(c)) {
+            value[offset] = (byte)c;
+        } else {
+            if (isLatin1()) {
+                inflate();
+            }
+            StringUTF16.putCharSB(value, offset, c);
+        }
         return this;
     }
 
@@ -1326,7 +1411,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str, int fromIndex) {
-        return String.indexOf(value, 0, count, str, fromIndex);
+        return String.indexOf(value, coder, count, str, fromIndex);
     }
 
     /**
@@ -1366,7 +1451,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str, int fromIndex) {
-        return String.lastIndexOf(value, 0, count, str, fromIndex);
+        return String.lastIndexOf(value, coder, count, str, fromIndex);
     }
 
     /**
@@ -1392,34 +1477,47 @@
      * @return  a reference to this object.
      */
     public AbstractStringBuilder reverse() {
-        boolean hasSurrogates = false;
+        byte[] val = this.value;
+        int count = this.count;
+        int coder = this.coder;
         int n = count - 1;
-        for (int j = (n-1) >> 1; j >= 0; j--) {
-            int k = n - j;
-            char cj = value[j];
-            char ck = value[k];
-            value[j] = ck;
-            value[k] = cj;
-            if (Character.isSurrogate(cj) ||
-                Character.isSurrogate(ck)) {
-                hasSurrogates = true;
+        if (COMPACT_STRINGS && coder == LATIN1) {
+            for (int j = (n-1) >> 1; j >= 0; j--) {
+                int k = n - j;
+                byte cj = val[j];
+                val[j] = val[k];
+                val[k] = cj;
             }
-        }
-        if (hasSurrogates) {
-            reverseAllValidSurrogatePairs();
+        } else {
+            checkOffset(count, val.length >> 1);
+            boolean hasSurrogates = false;
+            for (int j = (n-1) >> 1; j >= 0; j--) {
+                int k = n - j;
+                char cj = StringUTF16.getChar(val, j);
+                char ck = StringUTF16.getChar(val, k);
+                StringUTF16.putChar(val, j, ck);
+                StringUTF16.putChar(val, k, cj);
+                if (Character.isSurrogate(cj) ||
+                    Character.isSurrogate(ck)) {
+                    hasSurrogates = true;
+                }
+            }
+            if (hasSurrogates) {
+                reverseAllValidSurrogatePairs(val, count);
+            }
         }
         return this;
     }
 
     /** Outlined helper method for reverse() */
-    private void reverseAllValidSurrogatePairs() {
+    private void reverseAllValidSurrogatePairs(byte[] val, int count) {
         for (int i = 0; i < count - 1; i++) {
-            char c2 = value[i];
+            char c2 = StringUTF16.getChar(val, i);
             if (Character.isLowSurrogate(c2)) {
-                char c1 = value[i + 1];
+                char c1 = StringUTF16.getChar(val, i + 1);
                 if (Character.isHighSurrogate(c1)) {
-                    value[i++] = c1;
-                    value[i] = c2;
+                    StringUTF16.putChar(val, i++, c1);
+                    StringUTF16.putChar(val, i, c2);
                 }
             }
         }
@@ -1444,10 +1542,13 @@
      */
     @Override
     public IntStream chars() {
+        byte[] val = this.value; int count = this.count; byte coder = this.coder;
+        checkOffset(count, val.length >> coder);
         // Reuse String-based spliterator. This requires a supplier to
         // capture the value and count when the terminal operation is executed
         return StreamSupport.intStream(
-                () -> new String.IntCharArraySpliterator(value, 0, count, 0),
+                () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
+                                      : new StringUTF16.CharsSpliterator(val, 0, count, 0),
                 Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
                 false);
     }
@@ -1458,10 +1559,13 @@
      */
     @Override
     public IntStream codePoints() {
+        byte[] val = this.value; int count = this.count; byte coder = this.coder;
+        checkOffset(count, val.length >> coder);
         // Reuse String-based spliterator. This requires a supplier to
         // capture the value and count when the terminal operation is executed
         return StreamSupport.intStream(
-                () -> new String.CodePointsSpliterator(value, 0, count, 0),
+                () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
+                                      : new StringUTF16.CodePointsSpliterator(val, 0, count, 0),
                 Spliterator.ORDERED,
                 false);
     }
@@ -1469,8 +1573,147 @@
     /**
      * Needed by {@code String} for the contentEquals method.
      */
-    final char[] getValue() {
+    final byte[] getValue() {
         return value;
     }
 
+    /*
+     * Invoker guarantees it is in UTF16 (inflate itself for asb), if two
+     * coders are different and the dstBegin has enough space
+     *
+     * @param dstBegin  the char index, not offset of byte[]
+     * @param coder     the coder of dst[]
+     */
+    protected void getBytes(byte dst[], int dstBegin, byte coder) {
+        if (this.coder == coder) {
+            System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);
+        } else {        // this.coder == LATIN && coder == UTF16
+            StringLatin1.inflateSB(value, dst, dstBegin, count);
+        }
+    }
+
+    /* for readObject() */
+    protected void initBytes(char[] value, int off, int len) {
+        if (String.COMPACT_STRINGS) {
+            this.value = StringUTF16.compress(value, off, len);
+            if (this.value != null) {
+                this.coder = LATIN1;
+                return;
+            }
+        }
+        this.coder = UTF16;
+        this.value = StringUTF16.toBytes(value, off, len);
+    }
+
+    final byte getCoder() {
+        return COMPACT_STRINGS ? coder : UTF16;
+    }
+
+    final boolean isLatin1() {
+        return COMPACT_STRINGS && coder == LATIN1;
+    }
+
+    private final void putCharsAt(int index, char[] s, int off, int end) {
+        if (isLatin1()) {
+            byte[] val = this.value;
+            for (int i = off, j = index; i < end; i++) {
+                char c = s[i];
+                if (StringLatin1.canEncode(c)) {
+                    val[j++] = (byte)c;
+                } else {
+                    inflate();
+                    StringUTF16.putCharsSB(this.value, j, s, i, end);
+                    return;
+                }
+            }
+        } else {
+            StringUTF16.putCharsSB(this.value, index, s, off, end);
+        }
+    }
+
+    private final void putCharsAt(int index, CharSequence s, int off, int end) {
+        if (isLatin1()) {
+            byte[] val = this.value;
+            for (int i = off, j = index; i < end; i++) {
+                char c = s.charAt(i);
+                if (StringLatin1.canEncode(c)) {
+                    val[j++] = (byte)c;
+                } else {
+                    inflate();
+                    StringUTF16.putCharsSB(this.value, j, s, i, end);
+                    return;
+                }
+            }
+        } else {
+            StringUTF16.putCharsSB(this.value, index, s, off, end);
+        }
+    }
+
+    private final void putStringAt(int index, String str) {
+        if (getCoder() != str.coder()) {
+            inflate();
+        }
+        byte[] val = this.value;
+        byte coder = this.coder;
+        checkOffset(index + str.length(), val.length >> coder);
+        str.getBytes(val, index, coder);
+    }
+
+    private final void appendChars(char[] s, int off, int end) {
+        if (isLatin1()) {
+            byte[] val = this.value;
+            for (int i = off, j = count; i < end; i++) {
+                char c = s[i];
+                if (StringLatin1.canEncode(c)) {
+                    val[j++] = (byte)c;
+                } else {
+                    count = j;
+                    inflate();
+                    StringUTF16.putCharsSB(this.value, j, s, i, end);
+                    count += end - i;
+                    return;
+                }
+            }
+        } else {
+            StringUTF16.putCharsSB(this.value, count, s, off, end);
+        }
+        count += end - off;
+    }
+
+    private final void appendChars(CharSequence s, int off, int end) {
+        if (isLatin1()) {
+            byte[] val = this.value;
+            for (int i = off, j = count; i < end; i++) {
+                char c = s.charAt(i);
+                if (StringLatin1.canEncode(c)) {
+                    val[j++] = (byte)c;
+                } else {
+                    count = j;
+                    inflate();
+                    StringUTF16.putCharsSB(this.value, j, s, i, end);
+                    count += end - i;
+                    return;
+                }
+            }
+        } else {
+            StringUTF16.putCharsSB(this.value, count, s, off, end);
+        }
+        count += end - off;
+    }
+
+    /* IndexOutOfBoundsException, if out of bounds */
+    private static void checkRange(int start, int end, int len) {
+        if (start < 0 || start > end || end > len) {
+            throw new IndexOutOfBoundsException(
+                "start " + start + ", end " + end + ", length " + len);
+        }
+    }
+
+    /* StringIndexOutOfBoundsException, if out of bounds */
+    private static void checkRangeSIOOBE(int start, int end, int len) {
+        if (start < 0 || start > end || end > len) {
+            throw new StringIndexOutOfBoundsException(
+                "start " + start + ", end " + end + ", length " + len);
+        }
+    }
 }
--- a/jdk/src/java.base/share/classes/java/lang/Class.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java	Wed Jul 05 21:00:20 2017 +0200
@@ -55,7 +55,7 @@
 import java.util.HashMap;
 import java.util.Objects;
 import java.util.StringJoiner;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.HotSpotIntrinsicCandidate;
 import sun.reflect.CallerSensitive;
 import sun.reflect.ConstantPool;
--- a/jdk/src/java.base/share/classes/java/lang/Integer.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Integer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,6 +29,10 @@
 import java.util.Objects;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+
 /**
  * The {@code Integer} class wraps a value of the primitive type
  * {@code int} in an object. An object of type {@code Integer}
@@ -138,25 +142,47 @@
             return toString(i);
         }
 
-        char buf[] = new char[33];
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[33];
+            boolean negative = (i < 0);
+            int charPos = 32;
+
+            if (!negative) {
+                i = -i;
+            }
+
+            while (i <= -radix) {
+                buf[charPos--] = (byte)digits[-(i % radix)];
+                i = i / radix;
+            }
+            buf[charPos] = (byte)digits[-i];
+
+            if (negative) {
+                buf[--charPos] = '-';
+            }
+
+            return StringLatin1.newString(buf, charPos, (33 - charPos));
+        }
+        return toStringUTF16(i, radix);
+    }
+
+    private static String toStringUTF16(int i, int radix) {
+        byte[] buf = new byte[33 * 2];
         boolean negative = (i < 0);
         int charPos = 32;
-
         if (!negative) {
             i = -i;
         }
-
         while (i <= -radix) {
-            buf[charPos--] = digits[-(i % radix)];
+            StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
             i = i / radix;
         }
-        buf[charPos] = digits[-i];
+        StringUTF16.putChar(buf, charPos, digits[-i]);
 
         if (negative) {
-            buf[--charPos] = '-';
+            StringUTF16.putChar(buf, --charPos, '-');
         }
-
-        return new String(buf, charPos, (33 - charPos));
+        return StringUTF16.newString(buf, charPos, (33 - charPos));
     }
 
     /**
@@ -312,12 +338,16 @@
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-        char[] buf = new char[chars];
 
-        formatUnsignedInt(val, shift, buf, 0, chars);
-
-        // Use special constructor which takes over "buf".
-        return new String(buf, true);
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[chars];
+            formatUnsignedInt(val, shift, buf, 0, chars);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[chars * 2];
+            formatUnsignedIntUTF16(val, shift, buf, 0, chars);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
@@ -331,7 +361,7 @@
      * @param offset the offset in the destination buffer to start at
      * @param len the number of characters to write
      */
-     static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
+    static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         // assert offset >= 0 && offset < buf.length : "illegal offset";
         // assert len > 0 && (offset + len) <= buf.length : "illegal length";
@@ -344,6 +374,28 @@
         } while (charPos > offset);
     }
 
+    /** byte[]/LATIN1 version    */
+    static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            buf[--charPos] = (byte)Integer.digits[val & mask];
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
+    /** byte[]/UTF16 version    */
+    static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
     static final char [] DigitTens = {
         '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
         '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
@@ -401,9 +453,15 @@
         if (i == Integer.MIN_VALUE)
             return "-2147483648";
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
-        char[] buf = new char[size];
-        getChars(i, size, buf);
-        return new String(buf, true);
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[size];
+            getChars(i, size, buf);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[size * 2];
+            getCharsUTF16(i, size, buf);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
@@ -433,7 +491,7 @@
      *
      * Will fail if i == Integer.MIN_VALUE
      */
-    static void getChars(int i, int index, char[] buf) {
+    static void getChars(int i, int index, byte[] buf) {
         int q, r;
         int charPos = index;
         char sign = 0;
@@ -449,8 +507,8 @@
         // really: r = i - (q * 100);
             r = i - ((q << 6) + (q << 5) + (q << 2));
             i = q;
-            buf [--charPos] = DigitOnes[r];
-            buf [--charPos] = DigitTens[r];
+            buf [--charPos] = (byte)DigitOnes[r];
+            buf [--charPos] = (byte)DigitTens[r];
         }
 
         // Fall thru to fast mode for smaller numbers
@@ -458,12 +516,46 @@
         for (;;) {
             q = (i * 52429) >>> (16+3);
             r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
-            buf [--charPos] = digits [r];
+            buf [--charPos] = (byte)digits [r];
             i = q;
             if (i == 0) break;
         }
         if (sign != 0) {
-            buf [--charPos] = sign;
+            buf [--charPos] = (byte)sign;
+        }
+    }
+
+    static void getCharsUTF16(int i, int index, byte[] buf) {
+        int q, r;
+        int charPos = index;
+        char sign = 0;
+
+        if (i < 0) {
+            sign = '-';
+            i = -i;
+        }
+
+        // Generate two digits per iteration
+        while (i >= 65536) {
+            q = i / 100;
+        // really: r = i - (q * 100);
+            r = i - ((q << 6) + (q << 5) + (q << 2));
+            i = q;
+            StringUTF16.putChar(buf, --charPos, DigitOnes[r]);
+            StringUTF16.putChar(buf, --charPos, DigitTens[r]);
+        }
+
+        // Fall thru to fast mode for smaller numbers
+        // assert(i <= 65536, i);
+        for (;;) {
+            q = (i * 52429) >>> (16+3);
+            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
+            StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
+            i = q;
+            if (i == 0) break;
+        }
+        if (sign != 0) {
+            StringUTF16.putChar(buf, --charPos, sign);
         }
     }
 
--- a/jdk/src/java.base/share/classes/java/lang/Long.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Long.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,6 +30,9 @@
 import java.util.Objects;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
 
 /**
  * The {@code Long} class wraps a value of the primitive type {@code
@@ -124,25 +127,46 @@
             radix = 10;
         if (radix == 10)
             return toString(i);
-        char[] buf = new char[65];
+
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[65];
+            int charPos = 64;
+            boolean negative = (i < 0);
+
+            if (!negative) {
+                i = -i;
+            }
+
+            while (i <= -radix) {
+                buf[charPos--] = (byte)Integer.digits[(int)(-(i % radix))];
+                i = i / radix;
+            }
+            buf[charPos] = (byte)Integer.digits[(int)(-i)];
+
+            if (negative) {
+                buf[--charPos] = '-';
+            }
+            return StringLatin1.newString(buf, charPos, (65 - charPos));
+        }
+        return toStringUTF16(i, radix);
+    }
+
+    private static String toStringUTF16(long i, int radix) {
+        byte[] buf = new byte[65 * 2];
         int charPos = 64;
         boolean negative = (i < 0);
-
         if (!negative) {
             i = -i;
         }
-
         while (i <= -radix) {
-            buf[charPos--] = Integer.digits[(int)(-(i % radix))];
+            StringUTF16.putChar(buf, charPos--, Integer.digits[(int)(-(i % radix))]);
             i = i / radix;
         }
-        buf[charPos] = Integer.digits[(int)(-i)];
-
+        StringUTF16.putChar(buf, charPos, Integer.digits[(int)(-i)]);
         if (negative) {
-            buf[--charPos] = '-';
+            StringUTF16.putChar(buf, --charPos, '-');
         }
-
-        return new String(buf, charPos, (65 - charPos));
+        return StringUTF16.newString(buf, charPos, (65 - charPos));
     }
 
     /**
@@ -355,10 +379,16 @@
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Long.SIZE - Long.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-        char[] buf = new char[chars];
 
-        formatUnsignedLong(val, shift, buf, 0, chars);
-        return new String(buf, true);
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[chars];
+            formatUnsignedLong0(val, shift, buf, 0, chars);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[chars * 2];
+            formatUnsignedLong0UTF16(val, shift, buf, 0, chars);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
@@ -385,6 +415,28 @@
         } while (charPos > offset);
     }
 
+    /** byte[]/LATIN1 version    */
+    static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            buf[--charPos] = (byte)Integer.digits[((int) val) & mask];
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
+    /** byte[]/UTF16 version    */
+    static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            StringUTF16.putChar(buf, --charPos, Integer.digits[((int) val) & mask]);
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
     /**
      * Returns a {@code String} object representing the specified
      * {@code long}.  The argument is converted to signed decimal
@@ -399,9 +451,15 @@
         if (i == Long.MIN_VALUE)
             return "-9223372036854775808";
         int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
-        char[] buf = new char[size];
-        getChars(i, size, buf);
-        return new String(buf, true);
+        if (COMPACT_STRINGS) {
+            byte[] buf = new byte[size];
+            getChars(i, size, buf);
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[size * 2];
+            getCharsUTF16(i, size, buf);
+            return new String(buf, UTF16);
+        }
     }
 
     /**
@@ -431,7 +489,7 @@
      *
      * Will fail if i == Long.MIN_VALUE
      */
-    static void getChars(long i, int index, char[] buf) {
+    static void getChars(long i, int index, byte[] buf) {
         long q;
         int r;
         int charPos = index;
@@ -448,8 +506,8 @@
             // really: r = i - (q * 100);
             r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
             i = q;
-            buf[--charPos] = Integer.DigitOnes[r];
-            buf[--charPos] = Integer.DigitTens[r];
+            buf[--charPos] = (byte)Integer.DigitOnes[r];
+            buf[--charPos] = (byte)Integer.DigitTens[r];
         }
 
         // Get 2 digits/iteration using ints
@@ -460,8 +518,8 @@
             // really: r = i2 - (q * 100);
             r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
             i2 = q2;
-            buf[--charPos] = Integer.DigitOnes[r];
-            buf[--charPos] = Integer.DigitTens[r];
+            buf[--charPos] = (byte)Integer.DigitOnes[r];
+            buf[--charPos] = (byte)Integer.DigitTens[r];
         }
 
         // Fall thru to fast mode for smaller numbers
@@ -469,12 +527,59 @@
         for (;;) {
             q2 = (i2 * 52429) >>> (16+3);
             r = i2 - ((q2 << 3) + (q2 << 1));  // r = i2-(q2*10) ...
-            buf[--charPos] = Integer.digits[r];
+            buf[--charPos] = (byte)Integer.digits[r];
             i2 = q2;
             if (i2 == 0) break;
         }
         if (sign != 0) {
-            buf[--charPos] = sign;
+            buf[--charPos] = (byte)sign;
+        }
+    }
+
+    static void getCharsUTF16(long i, int index, byte[] buf) {
+        long q;
+        int r;
+        int charPos = index;
+        char sign = 0;
+
+        if (i < 0) {
+            sign = '-';
+            i = -i;
+        }
+
+        // Get 2 digits/iteration using longs until quotient fits into an int
+        while (i > Integer.MAX_VALUE) {
+            q = i / 100;
+            // really: r = i - (q * 100);
+            r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
+            i = q;
+            StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
+            StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
+        }
+
+        // Get 2 digits/iteration using ints
+        int q2;
+        int i2 = (int)i;
+        while (i2 >= 65536) {
+            q2 = i2 / 100;
+            // really: r = i2 - (q * 100);
+            r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
+            i2 = q2;
+            StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
+            StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
+        }
+
+        // Fall thru to fast mode for smaller numbers
+        // assert(i2 <= 65536, i2);
+        for (;;) {
+            q2 = (i2 * 52429) >>> (16+3);
+            r = i2 - ((q2 << 3) + (q2 << 1));  // r = i2-(q2*10) ...
+            StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
+            i2 = q2;
+            if (i2 == 0) break;
+        }
+        if (sign != 0) {
+            StringUTF16.putChar(buf, --charPos, sign);
         }
     }
 
--- a/jdk/src/java.base/share/classes/java/lang/Process.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/Process.java	Wed Jul 05 21:00:20 2017 +0200
@@ -83,7 +83,7 @@
  * {@link #getPid() process id},
  * {@link #info() information about the process},
  * {@link #children() direct children}, and
- * {@link #allChildren() direct and indirect children} of the process.
+ * {@link #descendants() direct children plus descendants of those children} of the process.
  * Delegating to the underlying Process or ProcessHandle is typically
  * easiest and most efficient.
  *
@@ -351,7 +351,7 @@
      * The {@link java.util.concurrent.CompletableFuture} provides the ability
      * to trigger dependent functions or actions that may be run synchronously
      * or asynchronously upon process termination.
-     * When the process terminates the CompletableFuture is
+     * When the process has terminated the CompletableFuture is
      * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
      * of the exit status of the process.
      * <p>
@@ -362,9 +362,6 @@
      * {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling}
      * the CompletableFuture does not affect the Process.
      * <p>
-     * If the process is {@link #isAlive not alive} the {@link CompletableFuture}
-     * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}.
-     * <p>
      * Processes returned from {@link ProcessBuilder#start} override the
      * default implementation to provide an efficient mechanism to wait
      * for process exit.
@@ -406,6 +403,9 @@
      *       return delegate.onExit().thenApply(p -> this);
      *    }
      * }</pre>
+     * @apiNote
+     * The process may be observed to have terminated with {@link #isAlive}
+     * before the ComputableFuture is completed and dependent actions are invoked.
      *
      * @return a new {@code CompletableFuture<Process>} for the Process
      *
@@ -464,7 +464,7 @@
      * {@link java.lang.UnsupportedOperationException} and performs no other action.
      * Subclasses should override this method to provide a ProcessHandle for the
      * process.  The methods {@link #getPid}, {@link #info}, {@link #children},
-     * and {@link #allChildren}, unless overridden, operate on the ProcessHandle.
+     * and {@link #descendants}, unless overridden, operate on the ProcessHandle.
      *
      * @return Returns a ProcessHandle for the Process
      * @throws UnsupportedOperationException if the Process implementation
@@ -481,9 +481,8 @@
     /**
      * Returns a snapshot of information about the process.
      *
-     * <p> An {@link ProcessHandle.Info} instance has various accessor methods
-     * that return information about the process, if the process is alive and
-     * the information is available, otherwise {@code null} is returned.
+     * <p> A {@link ProcessHandle.Info} instance has accessor methods
+     * that return information about the process if it is available.
      *
      * @implSpec
      * This implementation returns information about the process as:
@@ -524,9 +523,9 @@
     }
 
     /**
-     * Returns a snapshot of the direct and indirect children of the process.
-     * An indirect child is one whose parent is either a direct child or
-     * another indirect child.
+     * Returns a snapshot of the descendants of the process.
+     * The descendants of a process are the children of the process
+     * plus the descendants of those children, recursively.
      * Typically, a process that is {@link #isAlive not alive} has no children.
      * <p>
      * <em>Note that processes are created and terminate asynchronously.
@@ -535,18 +534,18 @@
      *
      * @implSpec
      * This implementation returns all children as:
-     * {@link #toHandle toHandle().allChildren()}.
+     * {@link #toHandle toHandle().descendants()}.
      *
-     * @return a sequential Stream of ProcessHandles for processes that are
-     *         direct and indirect children of the process
+     * @return a sequential Stream of ProcessHandles for processes that
+     *         are descendants of the process
      * @throws UnsupportedOperationException if the Process implementation
      *         does not support this operation
      * @throws SecurityException if a security manager has been installed and
      *         it denies RuntimePermission("manageProcess")
      * @since 1.9
      */
-    public Stream<ProcessHandle> allChildren() {
-        return toHandle().allChildren();
+    public Stream<ProcessHandle> descendants() {
+        return toHandle().descendants();
     }
 
 
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandle.java	Wed Jul 05 21:00:20 2017 +0200
@@ -54,7 +54,7 @@
  * Each ProcessHandle identifies and allows control of a process in the native
  * system. ProcessHandles are returned from the factory methods {@link #current()},
  * {@link #of(long)},
- * {@link #children}, {@link #allChildren}, {@link #parent()} and
+ * {@link #children}, {@link #descendants}, {@link #parent()} and
  * {@link #allProcesses()}.
  * <p>
  * The {@link Process} instances created by {@link ProcessBuilder} can be queried
@@ -164,21 +164,21 @@
     Stream<ProcessHandle> children();
 
     /**
-     * Returns a snapshot of the current direct and indirect children of the process.
-     * An indirect child is one whose parent is either a direct child or
-     * another indirect child.
+     * Returns a snapshot of the descendants of the process.
+     * The descendants of a process are the children of the process
+     * plus the descendants of those children, recursively.
      * Typically, a process that is {@link #isAlive not alive} has no children.
      * <p>
      * <em>Note that processes are created and terminate asynchronously.
      * There is no guarantee that a process is {@link #isAlive alive}.
      * </em>
      *
-     * @return a sequential Stream of ProcessHandles for processes that are
-     *         direct and indirect children of the process
+     * @return a sequential Stream of ProcessHandles for processes that
+     *         are descendants of the process
      * @throws SecurityException if a security manager has been installed and
      *         it denies RuntimePermission("manageProcess")
      */
-    Stream<ProcessHandle> allChildren();
+    Stream<ProcessHandle> descendants();
 
     /**
      * Returns a snapshot of all processes visible to the current process.
@@ -201,9 +201,8 @@
     /**
      * Returns a snapshot of information about the process.
      *
-     * <p> An {@code Info} instance has various accessor methods that return
-     * information about the process, if the process is alive and the
-     * information is available.
+     * <p> A {@link ProcessHandle.Info} instance has accessor methods that return
+     * information about the process if it is available.
      *
      * @return a snapshot of information about the process, always non-null
      */
@@ -288,7 +287,7 @@
      * The {@link java.util.concurrent.CompletableFuture} provides the ability
      * to trigger dependent functions or actions that may be run synchronously
      * or asynchronously upon process termination.
-     * When the process terminates the CompletableFuture is
+     * When the process has terminated the CompletableFuture is
      * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
      * of the exit status of the process.
      * The {@code onExit} method can be called multiple times to invoke
@@ -300,9 +299,9 @@
      * {@link java.util.concurrent.Future#get() wait} for it to terminate.
      * {@link java.util.concurrent.Future#cancel(boolean) Cancelling}
      * the CompleteableFuture does not affect the Process.
-     * <p>
-     * If the process is {@link #isAlive not alive} the {@link CompletableFuture}
-     * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}.
+     * @apiNote
+     * The process may be observed to have terminated with {@link #isAlive}
+     * before the ComputableFuture is completed and dependent actions are invoked.
      *
      * @return a new {@code CompletableFuture<ProcessHandle>} for the ProcessHandle
      *
--- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -389,7 +389,7 @@
     }
 
     @Override
-    public Stream<ProcessHandle> allChildren() {
+    public Stream<ProcessHandle> descendants() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(new RuntimePermission("manageProcess"));
--- a/jdk/src/java.base/share/classes/java/lang/String.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/String.java	Wed Jul 05 21:00:20 2017 +0200
@@ -36,7 +36,6 @@
 import java.util.Objects;
 import java.util.Spliterator;
 import java.util.StringJoiner;
-import java.util.function.IntConsumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
@@ -119,8 +118,19 @@
 
 public final class String
     implements java.io.Serializable, Comparable<String>, CharSequence {
+
     /** The value is used for character storage. */
-    private final char value[];
+    private final byte[] value;
+
+    /**
+     * The identifier of the encoding used to encode the bytes in
+     * {@code value}. The supported values in this implementation are
+     *
+     * LATIN1
+     * UTF16
+     *
+     */
+    private final byte coder;
 
     /** Cache the hash code for the string */
     private int hash; // Default to 0
@@ -129,6 +139,49 @@
     private static final long serialVersionUID = -6849794470754667710L;
 
     /**
+     * If String compaction is disabled, the bytes in {@code value} are
+     * always encoded in UTF16.
+     *
+     * For methods with several possible implementation paths, when String
+     * compaction is disabled, only one code path is taken.
+     *
+     * The instance field value is generally opaque to optimizing JIT
+     * compilers. Therefore, in performance-sensitive place, an explicit
+     * check of the static boolean {@code COMPACT_STRINGS} is done first
+     * before checking the {@code coder} field since the static boolean
+     * {@code COMPACT_STRINGS} would be constant folded away by an
+     * optimizing JIT compiler. The idioms for these cases are as follows.
+     *
+     * For code such as:
+     *
+     *    if (coder == LATIN1) { ... }
+     *
+     * can be written more optimally as
+     *
+     *    if (coder() == LATIN1) { ... }
+     *
+     * or:
+     *
+     *    if (COMPACT_STRINGS && coder == LATIN1) { ... }
+     *
+     * An optimizing JIT compiler can fold the above conditional as:
+     *
+     *    COMPACT_STRINGS == true  => if (coder == LATIN1) { ... }
+     *    COMPACT_STRINGS == false => if (false)           { ... }
+     *
+     * @implNote
+     * The actual value for this field is injected by JVM. The static
+     * initialization block is used to set the value here to communicate
+     * that this static final field is not statically foldable, and to
+     * avoid any possible circular dependency during vm initialization.
+     */
+    static final boolean COMPACT_STRINGS;
+
+    static {
+        COMPACT_STRINGS = true;
+    }
+
+    /**
      * Class String is special cased within the Serialization Stream Protocol.
      *
      * A String instance is written into an ObjectOutputStream according to
@@ -145,6 +198,7 @@
      */
     public String() {
         this.value = "".value;
+        this.coder = "".coder;
     }
 
     /**
@@ -160,6 +214,7 @@
     @HotSpotIntrinsicCandidate
     public String(String original) {
         this.value = original.value;
+        this.coder = original.coder;
         this.hash = original.hash;
     }
 
@@ -173,7 +228,7 @@
      *         The initial value of the string
      */
     public String(char value[]) {
-        this.value = Arrays.copyOf(value, value.length);
+        this(value, 0, value.length, null);
     }
 
     /**
@@ -198,23 +253,12 @@
      *          {@code offset} is greater than {@code value.length - count}
      */
     public String(char value[], int offset, int count) {
-        if (offset < 0) {
-            throw new StringIndexOutOfBoundsException(offset);
-        }
-        if (count <= 0) {
-            if (count < 0) {
-                throw new StringIndexOutOfBoundsException(count);
-            }
-            if (offset <= value.length) {
-                this.value = "".value;
-                return;
-            }
-        }
-        // Note: offset or count might be near -1>>>1.
-        if (offset > value.length - count) {
-            throw new StringIndexOutOfBoundsException(offset + count);
-        }
-        this.value = Arrays.copyOfRange(value, offset, offset + count);
+        this(value, offset, count, rangeCheck(value, offset, count));
+    }
+
+    private static Void rangeCheck(char[] value, int offset, int count) {
+        checkBoundsOffCount(offset, count, value.length);
+        return null;
     }
 
     /**
@@ -246,48 +290,22 @@
      * @since  1.5
      */
     public String(int[] codePoints, int offset, int count) {
-        if (offset < 0) {
-            throw new StringIndexOutOfBoundsException(offset);
+        checkBoundsOffCount(offset, count, codePoints.length);
+        if (count == 0) {
+            this.value = "".value;
+            this.coder = "".coder;
+            return;
         }
-        if (count <= 0) {
-            if (count < 0) {
-                throw new StringIndexOutOfBoundsException(count);
-            }
-            if (offset <= codePoints.length) {
-                this.value = "".value;
+        if (COMPACT_STRINGS) {
+            byte[] val = StringLatin1.toBytes(codePoints, offset, count);
+            if (val != null) {
+                this.coder = LATIN1;
+                this.value = val;
                 return;
             }
         }
-        // Note: offset or count might be near -1>>>1.
-        if (offset > codePoints.length - count) {
-            throw new StringIndexOutOfBoundsException(offset + count);
-        }
-
-        final int end = offset + count;
-
-        // Pass 1: Compute precise size of char[]
-        int n = count;
-        for (int i = offset; i < end; i++) {
-            int c = codePoints[i];
-            if (Character.isBmpCodePoint(c))
-                continue;
-            else if (Character.isValidCodePoint(c))
-                n++;
-            else throw new IllegalArgumentException(Integer.toString(c));
-        }
-
-        // Pass 2: Allocate and fill in char[]
-        final char[] v = new char[n];
-
-        for (int i = offset, j = 0; i < end; i++, j++) {
-            int c = codePoints[i];
-            if (Character.isBmpCodePoint(c))
-                v[j] = (char)c;
-            else
-                Character.toSurrogates(c, v, j++);
-        }
-
-        this.value = v;
+        this.coder = UTF16;
+        this.value = StringUTF16.toBytes(codePoints, offset, count);
     }
 
     /**
@@ -332,20 +350,24 @@
      */
     @Deprecated
     public String(byte ascii[], int hibyte, int offset, int count) {
-        checkBounds(ascii, offset, count);
-        char[] value = new char[count];
-
-        if (hibyte == 0) {
-            for (int i = count; i-- > 0;) {
-                value[i] = (char)(ascii[i + offset] & 0xff);
-            }
+        checkBoundsOffCount(offset, count, ascii.length);
+        if (count == 0) {
+            this.value = "".value;
+            this.coder = "".coder;
+            return;
+        }
+        if (COMPACT_STRINGS && (byte)hibyte == 0) {
+            this.value = Arrays.copyOfRange(ascii, offset, offset + count);
+            this.coder = LATIN1;
         } else {
             hibyte <<= 8;
-            for (int i = count; i-- > 0;) {
-                value[i] = (char)(hibyte | (ascii[i + offset] & 0xff));
+            byte[] val = StringUTF16.newBytesFor(count);
+            for (int i = 0; i < count; i++) {
+                StringUTF16.putChar(val, i, hibyte | (ascii[offset++] & 0xff));
             }
+            this.value = val;
+            this.coder = UTF16;
         }
-        this.value = value;
     }
 
     /**
@@ -383,19 +405,6 @@
         this(ascii, hibyte, 0, ascii.length);
     }
 
-    /* Common private utility method used to bounds check the byte array
-     * and requested offset & length values used by the String(byte[],..)
-     * constructors.
-     */
-    private static void checkBounds(byte[] bytes, int offset, int length) {
-        if (length < 0)
-            throw new StringIndexOutOfBoundsException(length);
-        if (offset < 0)
-            throw new StringIndexOutOfBoundsException(offset);
-        if (offset > bytes.length - length)
-            throw new StringIndexOutOfBoundsException(offset + length);
-    }
-
     /**
      * Constructs a new {@code String} by decoding the specified subarray of
      * bytes using the specified charset.  The length of the new {@code String}
@@ -433,8 +442,11 @@
             throws UnsupportedEncodingException {
         if (charsetName == null)
             throw new NullPointerException("charsetName");
-        checkBounds(bytes, offset, length);
-        this.value = StringCoding.decode(charsetName, bytes, offset, length);
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret =
+            StringCoding.decode(charsetName, bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
     }
 
     /**
@@ -470,8 +482,11 @@
     public String(byte bytes[], int offset, int length, Charset charset) {
         if (charset == null)
             throw new NullPointerException("charset");
-        checkBounds(bytes, offset, length);
-        this.value = StringCoding.decode(charset, bytes, offset, length);
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret =
+            StringCoding.decode(charset, bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
     }
 
     /**
@@ -553,8 +568,10 @@
      * @since  1.1
      */
     public String(byte bytes[], int offset, int length) {
-        checkBounds(bytes, offset, length);
-        this.value = StringCoding.decode(bytes, offset, length);
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret = StringCoding.decode(bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
     }
 
     /**
@@ -587,9 +604,7 @@
      *         A {@code StringBuffer}
      */
     public String(StringBuffer buffer) {
-        synchronized(buffer) {
-            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
-        }
+        this(buffer.toString());
     }
 
     /**
@@ -608,18 +623,20 @@
      * @since  1.5
      */
     public String(StringBuilder builder) {
-        this.value = Arrays.copyOf(builder.getValue(), builder.length());
+        this(builder, null);
     }
 
-    /*
+   /*
     * Package private constructor which shares value array for speed.
     * this constructor is always expected to be called with share==true.
     * a separate constructor is needed because we already have a public
     * String(char[]) constructor that makes a copy of the given char[].
     */
-    String(char[] value, boolean share) {
+    // TBD: this is kept for package internal use (Thread/System),
+    // should be removed if they all have a byte[] version
+    String(char[] val, boolean share) {
         // assert share : "unshared not supported";
-        this.value = value;
+        this(val, 0, val.length, null);
     }
 
     /**
@@ -631,7 +648,7 @@
      *          object.
      */
     public int length() {
-        return value.length;
+        return value.length >> coder();
     }
 
     /**
@@ -665,10 +682,11 @@
      *             string.
      */
     public char charAt(int index) {
-        if ((index < 0) || (index >= value.length)) {
-            throw new StringIndexOutOfBoundsException(index);
+        if (isLatin1()) {
+            return StringLatin1.charAt(value, index);
+        } else {
+            return StringUTF16.charAt(value, index);
         }
-        return value[index];
     }
 
     /**
@@ -694,10 +712,13 @@
      * @since      1.5
      */
     public int codePointAt(int index) {
-        if ((index < 0) || (index >= value.length)) {
-            throw new StringIndexOutOfBoundsException(index);
+        if (isLatin1()) {
+            checkIndex(index, value.length);
+            return value[index] & 0xff;
         }
-        return Character.codePointAtImpl(value, index, value.length);
+        int length = value.length >> 1;
+        checkIndex(index, length);
+        return StringUTF16.codePointAt(value, index, length);
     }
 
     /**
@@ -724,10 +745,13 @@
      */
     public int codePointBefore(int index) {
         int i = index - 1;
-        if ((i < 0) || (i >= value.length)) {
+        if (i < 0 || i >= length()) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        return Character.codePointBeforeImpl(value, index, 0);
+        if (isLatin1()) {
+            return (value[i] & 0xff);
+        }
+        return StringUTF16.codePointBefore(value, index);
     }
 
     /**
@@ -752,10 +776,14 @@
      * @since  1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
-        if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {
+        if (beginIndex < 0 || beginIndex > endIndex ||
+            endIndex > length()) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
+        if (isLatin1()) {
+            return endIndex - beginIndex;
+        }
+        return StringUTF16.codePointCount(value, beginIndex, endIndex);
     }
 
     /**
@@ -779,19 +807,10 @@
      * @since 1.5
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
-        if (index < 0 || index > value.length) {
+        if (index < 0 || index > length()) {
             throw new IndexOutOfBoundsException();
         }
-        return Character.offsetByCodePointsImpl(value, 0, value.length,
-                index, codePointOffset);
-    }
-
-    /**
-     * Copy characters from this string into dst starting at dstBegin.
-     * This method doesn't perform any range checking.
-     */
-    void getChars(char dst[], int dstBegin) {
-        System.arraycopy(value, 0, dst, dstBegin, value.length);
+        return Character.offsetByCodePoints(this, index, codePointOffset);
     }
 
     /**
@@ -825,16 +844,13 @@
      *                {@code dst.length}</ul>
      */
     public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
-        if (srcBegin < 0) {
-            throw new StringIndexOutOfBoundsException(srcBegin);
+        checkBoundsBeginEnd(srcBegin, srcEnd, length());
+        checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length);
+        if (isLatin1()) {
+            StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin);
+        } else {
+            StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin);
         }
-        if (srcEnd > value.length) {
-            throw new StringIndexOutOfBoundsException(srcEnd);
-        }
-        if (srcBegin > srcEnd) {
-            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
-        }
-        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
     }
 
     /**
@@ -882,24 +898,13 @@
      */
     @Deprecated
     public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
-        if (srcBegin < 0) {
-            throw new StringIndexOutOfBoundsException(srcBegin);
-        }
-        if (srcEnd > value.length) {
-            throw new StringIndexOutOfBoundsException(srcEnd);
-        }
-        if (srcBegin > srcEnd) {
-            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
-        }
+        checkBoundsBeginEnd(srcBegin, srcEnd, length());
         Objects.requireNonNull(dst);
-
-        int j = dstBegin;
-        int n = srcEnd;
-        int i = srcBegin;
-        char[] val = value;   /* avoid getfield opcode */
-
-        while (i < n) {
-            dst[j++] = (byte)val[i++];
+        checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length);
+        if (isLatin1()) {
+            StringLatin1.getBytes(value, srcBegin, srcEnd, dst, dstBegin);
+        } else {
+            StringUTF16.getBytes(value, srcBegin, srcEnd, dst, dstBegin);
         }
     }
 
@@ -926,7 +931,7 @@
     public byte[] getBytes(String charsetName)
             throws UnsupportedEncodingException {
         if (charsetName == null) throw new NullPointerException();
-        return StringCoding.encode(charsetName, value, 0, value.length);
+        return StringCoding.encode(charsetName, coder(), value);
     }
 
     /**
@@ -949,8 +954,8 @@
      */
     public byte[] getBytes(Charset charset) {
         if (charset == null) throw new NullPointerException();
-        return StringCoding.encode(charset, value, 0, value.length);
-    }
+        return StringCoding.encode(charset, coder(), value);
+     }
 
     /**
      * Encodes this {@code String} into a sequence of bytes using the
@@ -966,7 +971,7 @@
      * @since      1.1
      */
     public byte[] getBytes() {
-        return StringCoding.encode(value, 0, value.length);
+        return StringCoding.encode(coder(), value);
     }
 
     /**
@@ -987,23 +992,15 @@
      * @see  #compareTo(String)
      * @see  #equalsIgnoreCase(String)
      */
-    @HotSpotIntrinsicCandidate
     public boolean equals(Object anObject) {
         if (this == anObject) {
             return true;
         }
         if (anObject instanceof String) {
-            char[] v1 = value;
-            char[] v2 = ((String)anObject).value;
-            int n = v1.length;
-            if (n == v2.length) {
-                int i = 0;
-                while (n-- != 0) {
-                    if (v1[i] != v2[i])
-                        return false;
-                    i++;
-                }
-                return true;
+            String aString = (String)anObject;
+            if (coder() == aString.coder()) {
+                return isLatin1() ? StringLatin1.equals(value, aString.value)
+                                  : StringUTF16.equals(value, aString.value);
             }
         }
         return false;
@@ -1032,16 +1029,28 @@
     }
 
     private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
-        char[] v1 = value;
-        char[] v2 = sb.getValue();
-        int n = v1.length;
-        if (n != sb.length()) {
+        int len = length();
+        if (len != sb.length()) {
             return false;
         }
-        for (int i = 0; i < n; i++) {
-            if (v1[i] != v2[i]) {
+        byte v1[] = value;
+        byte v2[] = sb.getValue();
+        if (coder() == sb.getCoder()) {
+            int n = v1.length;
+            for (int i = 0; i < n; i++) {
+                if (v1[i] != v2[i]) {
+                    return false;
+                }
+            }
+        } else {
+            if (!isLatin1()) {  // utf16 str and latin1 abs can never be "equal"
                 return false;
             }
+            for (int i = 0; i < len; i++) {
+                if ((char)(v1[i] & 0xff) != StringUTF16.getChar(v2, i)) {
+                    return false;
+                }
+            }
         }
         return true;
     }
@@ -1081,14 +1090,22 @@
             return equals(cs);
         }
         // Argument is a generic CharSequence
-        char[] v1 = value;
-        int n = v1.length;
-        if (n != cs.length()) {
+        int n = cs.length();
+        if (n != length()) {
             return false;
         }
-        for (int i = 0; i < n; i++) {
-            if (v1[i] != cs.charAt(i)) {
-                return false;
+        byte[] val = this.value;
+        if (isLatin1()) {
+            for (int i = 0; i < n; i++) {
+                if ((val[i] & 0xff) != cs.charAt(i)) {
+                    return false;
+                }
+            }
+        } else {
+            for (int i = 0; i < n; i++) {
+                if (StringUTF16.getChar(val, i) != cs.charAt(i)) {
+                    return false;
+                }
             }
         }
         return true;
@@ -1125,8 +1142,8 @@
     public boolean equalsIgnoreCase(String anotherString) {
         return (this == anotherString) ? true
                 : (anotherString != null)
-                && (anotherString.value.length == value.length)
-                && regionMatches(true, 0, anotherString, 0, value.length);
+                && (anotherString.length() == length())
+                && regionMatches(true, 0, anotherString, 0, length());
     }
 
     /**
@@ -1173,23 +1190,16 @@
      *          value greater than {@code 0} if this string is
      *          lexicographically greater than the string argument.
      */
-    @HotSpotIntrinsicCandidate
     public int compareTo(String anotherString) {
-        char[] v1 = value;
-        char[] v2 = anotherString.value;
-        int len1 = v1.length;
-        int len2 = v2.length;
-        int lim = Math.min(len1, len2);
-
-        for (int k = 0; k < lim; k++) {
-            char c1 = v1[k];
-            char c2 = v2[k];
-            if (c1 != c2) {
-                return c1 - c2;
-            }
+        byte v1[] = value;
+        byte v2[] = anotherString.value;
+        if (coder() == anotherString.coder()) {
+            return isLatin1() ? StringLatin1.compareTo(v1, v2)
+                              : StringUTF16.compareTo(v1, v2);
         }
-        return len1 - len2;
-    }
+        return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
+                          : StringUTF16.compareToLatin1(v1, v2);
+     }
 
     /**
      * A Comparator that orders {@code String} objects as by
@@ -1210,12 +1220,18 @@
         private static final long serialVersionUID = 8575799808933029326L;
 
         public int compare(String s1, String s2) {
+            byte v1[] = s1.value;
+            byte v2[] = s2.value;
             int n1 = s1.length();
             int n2 = s2.length();
+            boolean s1IsLatin1 = s1.isLatin1();
+            boolean s2IsLatin1 = s2.isLatin1();
             int min = Math.min(n1, n2);
             for (int i = 0; i < min; i++) {
-                char c1 = s1.charAt(i);
-                char c2 = s2.charAt(i);
+                char c1 = s1IsLatin1 ? StringLatin1.getChar(v1, i)
+                                     : StringUTF16.getChar(v1, i);
+                char c2 = s2IsLatin1 ? StringLatin1.getChar(v2, i)
+                                     : StringUTF16.getChar(v2, i);
                 if (c1 != c2) {
                     c1 = Character.toUpperCase(c1);
                     c2 = Character.toUpperCase(c2);
@@ -1294,21 +1310,41 @@
      *          exactly matches the specified subregion of the string argument;
      *          {@code false} otherwise.
      */
-    public boolean regionMatches(int toffset, String other, int ooffset,
-            int len) {
-        char[] ta = value;
-        int to = toffset;
-        char[] pa = other.value;
-        int po = ooffset;
+    public boolean regionMatches(int toffset, String other, int ooffset, int len) {
+        byte tv[] = value;
+        byte ov[] = other.value;
         // Note: toffset, ooffset, or len might be near -1>>>1.
-        if ((ooffset < 0) || (toffset < 0)
-                || (toffset > (long)ta.length - len)
-                || (ooffset > (long)pa.length - len)) {
+        if ((ooffset < 0) || (toffset < 0) ||
+             (toffset > (long)length() - len) ||
+             (ooffset > (long)other.length() - len)) {
             return false;
         }
-        while (len-- > 0) {
-            if (ta[to++] != pa[po++]) {
-                return false;
+        if (coder() == other.coder()) {
+            if (!isLatin1() && (len > 0)) {
+                toffset = toffset << 1;
+                ooffset = ooffset << 1;
+                len = len << 1;
+            }
+            while (len-- > 0) {
+                if (tv[toffset++] != ov[ooffset++]) {
+                    return false;
+                }
+            }
+        } else {
+            if (coder() == LATIN1) {
+                while (len-- > 0) {
+                    if (StringLatin1.getChar(tv, toffset++) !=
+                        StringUTF16.getChar(ov, ooffset++)) {
+                        return false;
+                    }
+                }
+            } else {
+                while (len-- > 0) {
+                    if (StringUTF16.getChar(tv, toffset++) !=
+                        StringLatin1.getChar(ov, ooffset++)) {
+                        return false;
+                    }
+                }
             }
         }
         return true;
@@ -1366,43 +1402,25 @@
      */
     public boolean regionMatches(boolean ignoreCase, int toffset,
             String other, int ooffset, int len) {
-        char[] ta = value;
-        int to = toffset;
-        char[] pa = other.value;
-        int po = ooffset;
+        if (!ignoreCase) {
+            return regionMatches(toffset, other, ooffset, len);
+        }
         // Note: toffset, ooffset, or len might be near -1>>>1.
         if ((ooffset < 0) || (toffset < 0)
-                || (toffset > (long)ta.length - len)
-                || (ooffset > (long)pa.length - len)) {
+                || (toffset > (long)length() - len)
+                || (ooffset > (long)other.length() - len)) {
             return false;
         }
-        while (len-- > 0) {
-            char c1 = ta[to++];
-            char c2 = pa[po++];
-            if (c1 == c2) {
-                continue;
-            }
-            if (ignoreCase) {
-                // If characters don't match but case may be ignored,
-                // try converting both characters to uppercase.
-                // If the results match, then the comparison scan should
-                // continue.
-                char u1 = Character.toUpperCase(c1);
-                char u2 = Character.toUpperCase(c2);
-                if (u1 == u2) {
-                    continue;
-                }
-                // Unfortunately, conversion to uppercase does not work properly
-                // for the Georgian alphabet, which has strange rules about case
-                // conversion.  So we need to make one last check before
-                // exiting.
-                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
-                    continue;
-                }
-            }
-            return false;
+        byte tv[] = value;
+        byte ov[] = other.value;
+        if (coder() == other.coder()) {
+            return isLatin1()
+              ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len)
+              : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len);
         }
-        return true;
+        return isLatin1()
+              ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len)
+              : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len);
     }
 
     /**
@@ -1423,19 +1441,31 @@
      *          </pre>
      */
     public boolean startsWith(String prefix, int toffset) {
-        char[] ta = value;
-        int to = toffset;
-        char[] pa = prefix.value;
+        // Note: toffset might be near -1>>>1.
+        if (toffset < 0 || toffset > length() - prefix.length()) {
+            return false;
+        }
+        byte ta[] = value;
+        byte pa[] = prefix.value;
         int po = 0;
         int pc = pa.length;
-        // Note: toffset might be near -1>>>1.
-        if ((toffset < 0) || (toffset > ta.length - pc)) {
-            return false;
-        }
-        while (--pc >= 0) {
-            if (ta[to++] != pa[po++]) {
+        if (coder() == prefix.coder()) {
+            int to = isLatin1() ? toffset : toffset << 1;
+            while (po < pc) {
+                if (ta[to++] != pa[po++]) {
+                    return false;
+                }
+            }
+        } else {
+            if (isLatin1()) {  // && pcoder == UTF16
                 return false;
             }
+            // coder == UTF16 && pcoder == LATIN1)
+            while (po < pc) {
+                if (StringUTF16.getChar(ta, toffset++) != (pa[po++] & 0xff)) {
+                    return false;
+               }
+            }
         }
         return true;
     }
@@ -1469,7 +1499,7 @@
      *          as determined by the {@link #equals(Object)} method.
      */
     public boolean endsWith(String suffix) {
-        return startsWith(suffix, value.length - suffix.value.length);
+        return startsWith(suffix, length() - suffix.length());
     }
 
     /**
@@ -1486,16 +1516,11 @@
      * @return  a hash code value for this object.
      */
     public int hashCode() {
-        int h = hash;
-        if (h == 0) {
-            for (char v : value) {
-                h = 31 * h + v;
-            }
-            if (h != 0) {
-                hash = h;
-            }
+        if (hash == 0 && value.length > 0) {
+            hash = isLatin1() ? StringLatin1.hashCode(value)
+                              : StringUTF16.hashCode(value);
         }
-        return h;
+        return hash;
     }
 
     /**
@@ -1566,45 +1591,8 @@
      *          if the character does not occur.
      */
     public int indexOf(int ch, int fromIndex) {
-        final int max = value.length;
-        if (fromIndex < 0) {
-            fromIndex = 0;
-        } else if (fromIndex >= max) {
-            // Note: fromIndex might be near -1>>>1.
-            return -1;
-        }
-
-        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
-            // handle most cases here (ch is a BMP code point or a
-            // negative value (invalid code point))
-            final char[] value = this.value;
-            for (int i = fromIndex; i < max; i++) {
-                if (value[i] == ch) {
-                    return i;
-                }
-            }
-            return -1;
-        } else {
-            return indexOfSupplementary(ch, fromIndex);
-        }
-    }
-
-    /**
-     * Handles (rare) calls of indexOf with a supplementary character.
-     */
-    private int indexOfSupplementary(int ch, int fromIndex) {
-        if (Character.isValidCodePoint(ch)) {
-            final char[] value = this.value;
-            final char hi = Character.highSurrogate(ch);
-            final char lo = Character.lowSurrogate(ch);
-            final int max = value.length - 1;
-            for (int i = fromIndex; i < max; i++) {
-                if (value[i] == hi && value[i + 1] == lo) {
-                    return i;
-                }
-            }
-        }
-        return -1;
+        return isLatin1() ? StringLatin1.indexOf(value, ch, fromIndex)
+                          : StringUTF16.indexOf(value, ch, fromIndex);
     }
 
     /**
@@ -1631,7 +1619,7 @@
      *          {@code -1} if the character does not occur.
      */
     public int lastIndexOf(int ch) {
-        return lastIndexOf(ch, value.length - 1);
+        return lastIndexOf(ch, length() - 1);
     }
 
     /**
@@ -1669,38 +1657,8 @@
      *          if the character does not occur before that point.
      */
     public int lastIndexOf(int ch, int fromIndex) {
-        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
-            // handle most cases here (ch is a BMP code point or a
-            // negative value (invalid code point))
-            final char[] value = this.value;
-            int i = Math.min(fromIndex, value.length - 1);
-            for (; i >= 0; i--) {
-                if (value[i] == ch) {
-                    return i;
-                }
-            }
-            return -1;
-        } else {
-            return lastIndexOfSupplementary(ch, fromIndex);
-        }
-    }
-
-    /**
-     * Handles (rare) calls of lastIndexOf with a supplementary character.
-     */
-    private int lastIndexOfSupplementary(int ch, int fromIndex) {
-        if (Character.isValidCodePoint(ch)) {
-            final char[] value = this.value;
-            char hi = Character.highSurrogate(ch);
-            char lo = Character.lowSurrogate(ch);
-            int i = Math.min(fromIndex, value.length - 2);
-            for (; i >= 0; i--) {
-                if (value[i] == hi && value[i + 1] == lo) {
-                    return i;
-                }
-            }
-        }
-        return -1;
+        return isLatin1() ? StringLatin1.lastIndexOf(value, ch, fromIndex)
+                          : StringUTF16.lastIndexOf(value, ch, fromIndex);
     }
 
     /**
@@ -1717,9 +1675,15 @@
      * @return  the index of the first occurrence of the specified substring,
      *          or {@code -1} if there is no such occurrence.
      */
-    @HotSpotIntrinsicCandidate
     public int indexOf(String str) {
-        return indexOf(str, 0);
+        if (coder() == str.coder()) {
+            return isLatin1() ? StringLatin1.indexOf(value, str.value)
+                              : StringUTF16.indexOf(value, str.value);
+        }
+        if (coder() == LATIN1) {  // str.coder == UTF16
+            return -1;
+        }
+        return StringUTF16.indexOfLatin1(value, str.value);
     }
 
     /**
@@ -1740,8 +1704,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str, int fromIndex) {
-        return indexOf(value, 0, value.length,
-                str.value, 0, str.value.length, fromIndex);
+        return indexOf(value, coder(), length(), str, fromIndex);
     }
 
     /**
@@ -1749,68 +1712,38 @@
      * source is the character array being searched, and the target
      * is the string being searched for.
      *
-     * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
-     * @param   target       the characters being searched for.
-     * @param   fromIndex    the index to begin searching from.
+     * @param   src       the characters being searched.
+     * @param   srcCoder  the coder of the source string.
+     * @param   srcCount  length of the source string.
+     * @param   tgtStr    the characters being searched for.
+     * @param   fromIndex the index to begin searching from.
      */
-    static int indexOf(char[] source, int sourceOffset, int sourceCount,
-            String target, int fromIndex) {
-        return indexOf(source, sourceOffset, sourceCount,
-                       target.value, 0, target.value.length,
-                       fromIndex);
-    }
+    static int indexOf(byte[] src, byte srcCoder, int srcCount,
+                       String tgtStr, int fromIndex) {
 
-    /**
-     * Code shared by String and StringBuffer to do searches. The
-     * source is the character array being searched, and the target
-     * is the string being searched for.
-     *
-     * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
-     * @param   target       the characters being searched for.
-     * @param   targetOffset offset of the target string.
-     * @param   targetCount  count of the target string.
-     * @param   fromIndex    the index to begin searching from.
-     */
-    static int indexOf(char[] source, int sourceOffset, int sourceCount,
-            char[] target, int targetOffset, int targetCount,
-            int fromIndex) {
-        if (fromIndex >= sourceCount) {
-            return (targetCount == 0 ? sourceCount : -1);
+        byte[] tgt    = tgtStr.value;
+        byte tgtCoder = tgtStr.coder();
+        int tgtCount  = tgtStr.length();
+
+        if (fromIndex >= srcCount) {
+            return (tgtCount == 0 ? srcCount : -1);
         }
         if (fromIndex < 0) {
             fromIndex = 0;
         }
-        if (targetCount == 0) {
+        if (tgtCount == 0) {
             return fromIndex;
         }
-
-        char first = target[targetOffset];
-        int max = sourceOffset + (sourceCount - targetCount);
-
-        for (int i = sourceOffset + fromIndex; i <= max; i++) {
-            /* Look for first character. */
-            if (source[i] != first) {
-                while (++i <= max && source[i] != first);
-            }
-
-            /* Found first character, now look at the rest of v2 */
-            if (i <= max) {
-                int j = i + 1;
-                int end = j + targetCount - 1;
-                for (int k = targetOffset + 1; j < end && source[j]
-                        == target[k]; j++, k++);
-
-                if (j == end) {
-                    /* Found whole string. */
-                    return i - sourceOffset;
-                }
-            }
+        if (srcCoder == tgtCoder) {
+            return srcCoder == LATIN1
+                ? StringLatin1.indexOf(src, srcCount, tgt, tgtCount, fromIndex)
+                : StringUTF16.indexOf(src, srcCount, tgt, tgtCount, fromIndex);
         }
-        return -1;
+        if (srcCoder == LATIN1) {    //  && tgtCoder == UTF16
+            return -1;
+        }
+        // srcCoder == UTF16 && tgtCoder == LATIN1) {
+        return StringUTF16.indexOfLatin1(src, srcCount, tgt, tgtCount, fromIndex);
     }
 
     /**
@@ -1829,7 +1762,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str) {
-        return lastIndexOf(str, value.length);
+        return lastIndexOf(str, length());
     }
 
     /**
@@ -1850,8 +1783,7 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str, int fromIndex) {
-        return lastIndexOf(value, 0, value.length,
-                str.value, 0, str.value.length, fromIndex);
+        return lastIndexOf(value, coder(), length(), str, fromIndex);
     }
 
     /**
@@ -1859,40 +1791,22 @@
      * source is the character array being searched, and the target
      * is the string being searched for.
      *
-     * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
-     * @param   target       the characters being searched for.
-     * @param   fromIndex    the index to begin searching from.
+     * @param   src         the characters being searched.
+     * @param   srcCoder  coder handles the mapping between bytes/chars
+     * @param   srcCount    count of the source string.
+     * @param   tgt         the characters being searched for.
+     * @param   fromIndex   the index to begin searching from.
      */
-    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
-            String target, int fromIndex) {
-        return lastIndexOf(source, sourceOffset, sourceCount,
-                       target.value, 0, target.value.length,
-                       fromIndex);
-    }
-
-    /**
-     * Code shared by String and StringBuffer to do searches. The
-     * source is the character array being searched, and the target
-     * is the string being searched for.
-     *
-     * @param   source       the characters being searched.
-     * @param   sourceOffset offset of the source string.
-     * @param   sourceCount  count of the source string.
-     * @param   target       the characters being searched for.
-     * @param   targetOffset offset of the target string.
-     * @param   targetCount  count of the target string.
-     * @param   fromIndex    the index to begin searching from.
-     */
-    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
-            char[] target, int targetOffset, int targetCount,
-            int fromIndex) {
+    static int lastIndexOf(byte[] src, byte srcCoder, int srcCount,
+                           String tgtStr, int fromIndex) {
+        byte[] tgt = tgtStr.value;
+        byte tgtCoder = tgtStr.coder();
+        int tgtCount = tgtStr.length();
         /*
          * Check arguments; return immediately where possible. For
          * consistency, don't check for null str.
          */
-        int rightIndex = sourceCount - targetCount;
+        int rightIndex = srcCount - tgtCount;
         if (fromIndex < 0) {
             return -1;
         }
@@ -1900,34 +1814,41 @@
             fromIndex = rightIndex;
         }
         /* Empty string always matches. */
-        if (targetCount == 0) {
+        if (tgtCount == 0) {
             return fromIndex;
         }
+        if (srcCoder == tgtCoder) {
+            return srcCoder == LATIN1
+                ? StringLatin1.lastIndexOf(src, srcCount, tgt, tgtCount, fromIndex)
+                : StringUTF16.lastIndexOf(src, srcCount, tgt, tgtCount, fromIndex);
+        }
+        if (srcCoder == LATIN1) {    // && tgtCoder == UTF16
+            return -1;
+        }
+                                     // srcCoder == UTF16 && tgtCoder == LATIN1
+        int min = tgtCount - 1;
+        int i = min + fromIndex;
+        int strLastIndex = tgtCount - 1;
 
-        int strLastIndex = targetOffset + targetCount - 1;
-        char strLastChar = target[strLastIndex];
-        int min = sourceOffset + targetCount - 1;
-        int i = min + fromIndex;
-
+        char strLastChar = (char)(tgt[strLastIndex] & 0xff);
     startSearchForLastChar:
         while (true) {
-            while (i >= min && source[i] != strLastChar) {
+            while (i >= min && StringUTF16.getChar(src, i) != strLastChar) {
                 i--;
             }
             if (i < min) {
                 return -1;
             }
             int j = i - 1;
-            int start = j - (targetCount - 1);
+            int start = j - strLastIndex;
             int k = strLastIndex - 1;
-
             while (j > start) {
-                if (source[j--] != target[k--]) {
+                if (StringUTF16.getChar(src, j--) != (tgt[k--] & 0xff)) {
                     i--;
                     continue startSearchForLastChar;
                 }
             }
-            return start - sourceOffset + 1;
+            return start + 1;
         }
     }
 
@@ -1949,17 +1870,18 @@
      *             length of this {@code String} object.
      */
     public String substring(int beginIndex) {
-        if (beginIndex <= 0) {
-            if (beginIndex < 0) {
-                throw new StringIndexOutOfBoundsException(beginIndex);
-            }
-            return this;
+        if (beginIndex < 0) {
+            throw new StringIndexOutOfBoundsException(beginIndex);
         }
-        int subLen = value.length - beginIndex;
+        int subLen = length() - beginIndex;
         if (subLen < 0) {
             throw new StringIndexOutOfBoundsException(subLen);
         }
-        return new String(value, beginIndex, subLen);
+        if (beginIndex == 0) {
+            return this;
+        }
+        return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
+                          : StringUTF16.newString(value, beginIndex, subLen);
     }
 
     /**
@@ -1985,22 +1907,14 @@
      *             {@code endIndex}.
      */
     public String substring(int beginIndex, int endIndex) {
-        if (beginIndex <= 0) {
-            if (beginIndex < 0) {
-                throw new StringIndexOutOfBoundsException(beginIndex);
-            }
-            if (endIndex == value.length) {
-                return this;
-            }
+        int length = length();
+        checkBoundsBeginEnd(beginIndex, endIndex, length);
+        int subLen = endIndex - beginIndex;
+        if (beginIndex == 0 && endIndex == length) {
+            return this;
         }
-        if (endIndex > value.length) {
-            throw new StringIndexOutOfBoundsException(endIndex);
-        }
-        int subLen = endIndex - beginIndex;
-        if (subLen < 0) {
-            throw new StringIndexOutOfBoundsException(subLen);
-        }
-        return new String(value, beginIndex, subLen);
+        return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
+                          : StringUTF16.newString(value, beginIndex, subLen);
     }
 
     /**
@@ -2057,14 +1971,23 @@
      *          characters followed by the string argument's characters.
      */
     public String concat(String str) {
-        int otherLen = str.length();
-        if (otherLen == 0) {
+        int olen = str.length();
+        if (olen == 0) {
             return this;
         }
-        int len = value.length;
-        char[] buf = Arrays.copyOf(value, len + otherLen);
-        str.getChars(buf, len);
-        return new String(buf, true);
+        if (coder() == str.coder()) {
+            byte[] val = this.value;
+            byte[] oval = str.value;
+            int len = val.length + oval.length;
+            byte[] buf = Arrays.copyOf(val, len);
+            System.arraycopy(oval, 0, buf, val.length, oval.length);
+            return new String(buf, coder);
+        }
+        int len = length();
+        byte[] buf = StringUTF16.newBytesFor(len + olen);
+        getBytes(buf, 0, UTF16);
+        str.getBytes(buf, len, UTF16);
+        return new String(buf, UTF16);
     }
 
     /**
@@ -2098,26 +2021,10 @@
      */
     public String replace(char oldChar, char newChar) {
         if (oldChar != newChar) {
-            char[] val = value; /* avoid getfield opcode */
-            int len = val.length;
-            int i = -1;
-
-            while (++i < len) {
-                if (val[i] == oldChar) {
-                    break;
-                }
-            }
-            if (i < len) {
-                char[] buf = new char[len];
-                for (int j = 0; j < i; j++) {
-                    buf[j] = val[j];
-                }
-                while (i < len) {
-                    char c = val[i];
-                    buf[i] = (c == oldChar) ? newChar : c;
-                    i++;
-                }
-                return new String(buf, true);
+            String ret = isLatin1() ? StringLatin1.replace(value, oldChar, newChar)
+                                    : StringUTF16.replace(value, oldChar, newChar);
+            if (ret != null) {
+                return ret;
             }
         }
         return this;
@@ -2269,29 +2176,27 @@
      * @since 1.5
      */
     public String replace(CharSequence target, CharSequence replacement) {
-        String starget = target.toString();
-        String srepl = replacement.toString();
-        int j = indexOf(starget);
+        String tgtStr = target.toString();
+        String replStr = replacement.toString();
+        int j = indexOf(tgtStr);
         if (j < 0) {
             return this;
         }
-        int targLen = starget.length();
-        int targLen1 = Math.max(targLen, 1);
-        final char[] value = this.value;
-        final char[] replValue = srepl.value;
-        int newLenHint = value.length - targLen + replValue.length;
+        int tgtLen = tgtStr.length();
+        int tgtLen1 = Math.max(tgtLen, 1);
+        int thisLen = length();
+
+        int newLenHint = thisLen - tgtLen + replStr.length();
         if (newLenHint < 0) {
             throw new OutOfMemoryError();
         }
         StringBuilder sb = new StringBuilder(newLenHint);
         int i = 0;
         do {
-            sb.append(value, i, j - i)
-                    .append(replValue);
-            i = j + targLen;
-        } while (j < value.length && (j = indexOf(starget, j + targLen1)) > 0);
-
-        return sb.append(value, i, value.length - i).toString();
+            sb.append(this, i, j).append(replStr);
+            i = j + tgtLen;
+        } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
+        return sb.append(this, i, thisLen).toString();
     }
 
     /**
@@ -2388,7 +2293,7 @@
             the second is not the ascii digit or ascii letter.
          */
         char ch = 0;
-        if (((regex.value.length == 1 &&
+        if (((regex.length() == 1 &&
              ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
              (regex.length() == 2 &&
               regex.charAt(0) == '\\' &&
@@ -2408,8 +2313,9 @@
                     off = next + 1;
                 } else {    // last one
                     //assert (list.size() == limit - 1);
-                    list.add(substring(off, value.length));
-                    off = value.length;
+                    int last = length();
+                    list.add(substring(off, last));
+                    off = last;
                     break;
                 }
             }
@@ -2419,7 +2325,7 @@
 
             // Add remaining segment
             if (!limited || list.size() < limit)
-                list.add(substring(off, value.length));
+                list.add(substring(off, length()));
 
             // Construct result
             int resultSize = list.size();
@@ -2613,95 +2519,8 @@
      * @since   1.1
      */
     public String toLowerCase(Locale locale) {
-        if (locale == null) {
-            throw new NullPointerException();
-        }
-        int first;
-        boolean hasSurr = false;
-        final int len = value.length;
-
-        // Now check if there are any characters that need to be changed, or are surrogate
-        for (first = 0 ; first < len; first++) {
-            int cp = (int)value[first];
-            if (Character.isSurrogate((char)cp)) {
-                hasSurr = true;
-                break;
-            }
-            if (cp != Character.toLowerCase(cp)) {  // no need to check Character.ERROR
-                break;
-            }
-        }
-        if (first == len)
-            return this;
-        char[] result = new char[len];
-        System.arraycopy(value, 0, result, 0, first);  // Just copy the first few
-                                                       // lowerCase characters.
-        String lang = locale.getLanguage();
-        if (lang == "tr" || lang == "az" || lang == "lt") {
-            return toLowerCaseEx(result, first, locale, true);
-        }
-        if (hasSurr) {
-            return toLowerCaseEx(result, first, locale, false);
-        }
-        for (int i = first; i < len; i++) {
-            int cp = (int)value[i];
-            if (cp == '\u03A3' ||                       // GREEK CAPITAL LETTER SIGMA
-                Character.isSurrogate((char)cp)) {
-                return toLowerCaseEx(result, i, locale, false);
-            }
-            if (cp == '\u0130') {                       // LATIN CAPITAL LETTER I WITH DOT ABOVE
-                return toLowerCaseEx(result, i, locale, true);
-            }
-            cp = Character.toLowerCase(cp);
-            if (!Character.isBmpCodePoint(cp)) {
-                return toLowerCaseEx(result, i, locale, false);
-            }
-            result[i] = (char)cp;
-        }
-        return new String(result, true);
-    }
-
-    private String toLowerCaseEx(char[] result, int first, Locale locale, boolean localeDependent) {
-        int resultOffset = first;
-        int srcCount;
-        for (int i = first; i < value.length; i += srcCount) {
-            int srcChar = (int)value[i];
-            int lowerChar;
-            char[] lowerCharArray;
-            srcCount = 1;
-            if (Character.isSurrogate((char)srcChar)) {
-                srcChar = codePointAt(i);
-                srcCount = Character.charCount(srcChar);
-            }
-            if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA
-                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(this, i, locale);
-            } else {
-                lowerChar = Character.toLowerCase(srcChar);
-            }
-            if (Character.isBmpCodePoint(lowerChar)) {    // Character.ERROR is not a bmp
-                result[resultOffset++] = (char)lowerChar;
-            } else {
-                if (lowerChar == Character.ERROR) {
-                    lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(this, i, locale);
-                } else if (srcCount == 2) {
-                    resultOffset += Character.toChars(lowerChar, result, resultOffset);
-                    continue;
-                } else {
-                    lowerCharArray = Character.toChars(lowerChar);
-                }
-                /* Grow result if needed */
-                int mapLen = lowerCharArray.length;
-                if (mapLen > srcCount) {
-                    char[] result2 = new char[result.length + mapLen - srcCount];
-                    System.arraycopy(result, 0, result2, 0, resultOffset);
-                    result = result2;
-                }
-                for (int x = 0; x < mapLen; ++x) {
-                    result[resultOffset++] = lowerCharArray[x];
-                }
-            }
-        }
-        return new String(result, 0, resultOffset);
+        return isLatin1() ? StringLatin1.toLowerCase(this, value, locale)
+                          : StringUTF16.toLowerCase(this, value, locale);
     }
 
     /**
@@ -2776,98 +2595,8 @@
      * @since   1.1
      */
     public String toUpperCase(Locale locale) {
-        if (locale == null) {
-            throw new NullPointerException();
-        }
-        int first;
-        boolean hasSurr = false;
-        final int len = value.length;
-
-        // Now check if there are any characters that need to be changed, or are surrogate
-        for (first = 0 ; first < len; first++ ) {
-            int cp = (int)value[first];
-            if (Character.isSurrogate((char)cp)) {
-                hasSurr = true;
-                break;
-            }
-            if (cp != Character.toUpperCaseEx(cp)) {   // no need to check Character.ERROR
-                break;
-            }
-        }
-        if (first == len) {
-            return this;
-        }
-        char[] result = new char[len];
-        System.arraycopy(value, 0, result, 0, first);  // Just copy the first few
-                                                       // upperCase characters.
-        String lang = locale.getLanguage();
-        if (lang == "tr" || lang == "az" || lang == "lt") {
-            return toUpperCaseEx(result, first, locale, true);
-        }
-        if (hasSurr) {
-            return toUpperCaseEx(result, first, locale, false);
-        }
-        for (int i = first; i < len; i++) {
-            int cp = (int)value[i];
-            if (Character.isSurrogate((char)cp)) {
-                return toUpperCaseEx(result, i, locale, false);
-            }
-            cp = Character.toUpperCaseEx(cp);
-            if (!Character.isBmpCodePoint(cp)) {    // Character.ERROR is not bmp
-                return toUpperCaseEx(result, i, locale, false);
-            }
-            result[i] = (char)cp;
-        }
-        return new String(result, true);
-    }
-
-    private String toUpperCaseEx(char[] result, int first, Locale locale,
-                                 boolean localeDependent) {
-        int resultOffset = first;
-        int srcCount;
-        for (int i = first; i < value.length; i += srcCount) {
-            int srcChar = (int)value[i];
-            int upperChar;
-            char[] upperCharArray;
-            srcCount = 1;
-            if (Character.isSurrogate((char)srcChar)) {
-                srcChar = codePointAt(i);
-                srcCount = Character.charCount(srcChar);
-            }
-            if (localeDependent) {
-                upperChar = ConditionalSpecialCasing.toUpperCaseEx(this, i, locale);
-            } else {
-                upperChar = Character.toUpperCaseEx(srcChar);
-            }
-            if (Character.isBmpCodePoint(upperChar)) {
-                result[resultOffset++] = (char)upperChar;
-            } else {
-                if (upperChar == Character.ERROR) {
-                    if (localeDependent) {
-                        upperCharArray =
-                            ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale);
-                    } else {
-                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
-                    }
-                } else if (srcCount == 2) {
-                    resultOffset += Character.toChars(upperChar, result, resultOffset);
-                    continue;
-                } else {
-                    upperCharArray = Character.toChars(upperChar);
-                }
-                /* Grow result if needed */
-                int mapLen = upperCharArray.length;
-                if (mapLen > srcCount) {
-                    char[] result2 = new char[result.length + mapLen - srcCount];
-                    System.arraycopy(result, 0, result2, 0, resultOffset);
-                    result = result2;
-                 }
-                 for (int x = 0; x < mapLen; ++x) {
-                    result[resultOffset++] = upperCharArray[x];
-                 }
-            }
-        }
-        return new String(result, 0, resultOffset);
+        return isLatin1() ? StringLatin1.toUpperCase(this, value, locale)
+                          : StringUTF16.toUpperCase(this, value, locale);
     }
 
     /**
@@ -2925,17 +2654,9 @@
      *          trailing white space.
      */
     public String trim() {
-        char[] val = value;    /* avoid getfield opcode */
-        int end = val.length;
-        int beg = 0;
-
-        while ((beg < end) && (val[beg] <= ' ')) {
-            beg++;
-        }
-        while ((beg < end) && (val[end - 1] <= ' ')) {
-            end--;
-        }
-        return substring(beg, end);
+        String ret = isLatin1() ? StringLatin1.trim(value)
+                                : StringUTF16.trim(value);
+        return ret == null ? this : ret;
     }
 
     /**
@@ -2947,63 +2668,6 @@
         return this;
     }
 
-    static class IntCharArraySpliterator implements Spliterator.OfInt {
-        private final char[] array;
-        private int index;        // current index, modified on advance/split
-        private final int fence;  // one past last index
-        private final int cs;
-
-        IntCharArraySpliterator(char[] array, int acs) {
-            this(array, 0, array.length, acs);
-        }
-
-        IntCharArraySpliterator(char[] array, int origin, int fence, int acs) {
-            this.array = array;
-            this.index = origin;
-            this.fence = fence;
-            this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
-                      | Spliterator.SUBSIZED;
-        }
-
-        @Override
-        public OfInt trySplit() {
-            int lo = index, mid = (lo + fence) >>> 1;
-            return (lo >= mid)
-                   ? null
-                   : new IntCharArraySpliterator(array, lo, index = mid, cs);
-        }
-
-        @Override
-        public void forEachRemaining(IntConsumer action) {
-            char[] a; int i, hi; // hoist accesses and checks from loop
-            if (action == null)
-                throw new NullPointerException();
-            if ((a = array).length >= (hi = fence) &&
-                (i = index) >= 0 && i < (index = hi)) {
-                do { action.accept(a[i]); } while (++i < hi);
-            }
-        }
-
-        @Override
-        public boolean tryAdvance(IntConsumer action) {
-            if (action == null)
-                throw new NullPointerException();
-            if (index >= 0 && index < fence) {
-                action.accept(array[index++]);
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public long estimateSize() { return (long)(fence - index); }
-
-        @Override
-        public int characteristics() {
-            return cs;
-        }
-    }
-
     /**
      * Returns a stream of {@code int} zero-extending the {@code char} values
      * from this sequence.  Any char which maps to a <a
@@ -3016,93 +2680,11 @@
     @Override
     public IntStream chars() {
         return StreamSupport.intStream(
-                new IntCharArraySpliterator(value, Spliterator.IMMUTABLE), false);
+            isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE)
+                       : new StringUTF16.CharsSpliterator(value, Spliterator.IMMUTABLE),
+            false);
     }
 
-    static class CodePointsSpliterator implements Spliterator.OfInt {
-        private final char[] array;
-        private int index;        // current index, modified on advance/split
-        private final int fence;  // one past last index
-        private final int cs;
-
-        CodePointsSpliterator(char[] array, int acs) {
-            this(array, 0, array.length, acs);
-        }
-
-        CodePointsSpliterator(char[] array, int origin, int fence, int acs) {
-            this.array = array;
-            this.index = origin;
-            this.fence = fence;
-            this.cs = acs | Spliterator.ORDERED;
-        }
-
-        @Override
-        public OfInt trySplit() {
-            int lo = index, mid = (lo + fence) >>> 1;
-            if (lo >= mid)
-                return null;
-
-            int midOneLess;
-            // If the mid-point intersects a surrogate pair
-            if (Character.isLowSurrogate(array[mid]) &&
-                Character.isHighSurrogate(array[midOneLess = (mid -1)])) {
-                // If there is only one pair it cannot be split
-                if (lo >= midOneLess)
-                    return null;
-                // Shift the mid-point to align with the surrogate pair
-                return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
-            }
-            return new CodePointsSpliterator(array, lo, index = mid, cs);
-        }
-
-        @Override
-        public void forEachRemaining(IntConsumer action) {
-            char[] a; int i, hi; // hoist accesses and checks from loop
-            if (action == null)
-                throw new NullPointerException();
-            if ((a = array).length >= (hi = fence) &&
-                (i = index) >= 0 && i < (index = hi)) {
-                do {
-                    i = advance(a, i, hi, action);
-                } while (i < hi);
-            }
-        }
-
-        @Override
-        public boolean tryAdvance(IntConsumer action) {
-            if (action == null)
-                throw new NullPointerException();
-            if (index >= 0 && index < fence) {
-                index = advance(array, index, fence, action);
-                return true;
-            }
-            return false;
-        }
-
-        // Advance one code point from the index, i, and return the next
-        // index to advance from
-        private static int advance(char[] a, int i, int hi, IntConsumer action) {
-            char c1 = a[i++];
-            int cp = c1;
-            if (Character.isHighSurrogate(c1) && i < hi) {
-                char c2 = a[i];
-                if (Character.isLowSurrogate(c2)) {
-                    i++;
-                    cp = Character.toCodePoint(c1, c2);
-                }
-            }
-            action.accept(cp);
-            return i;
-        }
-
-        @Override
-        public long estimateSize() { return (long)(fence - index); }
-
-        @Override
-        public int characteristics() {
-            return cs;
-        }
-    }
 
     /**
      * Returns a stream of code point values from this sequence.  Any surrogate
@@ -3118,7 +2700,9 @@
     @Override
     public IntStream codePoints() {
         return StreamSupport.intStream(
-                new CodePointsSpliterator(value, Spliterator.IMMUTABLE), false);
+            isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE)
+                       : new StringUTF16.CodePointsSpliterator(value, Spliterator.IMMUTABLE),
+            false);
     }
 
     /**
@@ -3129,10 +2713,8 @@
      *          the character sequence represented by this string.
      */
     public char[] toCharArray() {
-        // Cannot use Arrays.copyOf because of class initialization order issues
-        char[] result = new char[value.length];
-        System.arraycopy(value, 0, result, 0, value.length);
-        return result;
+        return isLatin1() ? StringLatin1.toChars(value)
+                          : StringUTF16.toChars(value);
     }
 
     /**
@@ -3315,7 +2897,10 @@
      *          as its single character the argument {@code c}.
      */
     public static String valueOf(char c) {
-        return new String(new char[]{c}, true);
+        if (COMPACT_STRINGS && StringLatin1.canEncode(c)) {
+            return new String(StringLatin1.toBytes(c), LATIN1);
+        }
+        return new String(StringUTF16.toBytes(c), UTF16);
     }
 
     /**
@@ -3398,4 +2983,145 @@
      *          guaranteed to be from a pool of unique strings.
      */
     public native String intern();
+
+    ////////////////////////////////////////////////////////////////
+
+    /**
+     * Copy character bytes from this string into dst starting at dstBegin.
+     * This method doesn't perform any range checking.
+     *
+     * Invoker guarantees: dst is in UTF16 (inflate itself for asb), if two
+     * coders are different, and dst is big enough (range check)
+     *
+     * @param dstBegin  the char index, not offset of byte[]
+     * @param coder     the coder of dst[]
+     */
+    void getBytes(byte dst[], int dstBegin, byte coder) {
+        if (coder() == coder) {
+            System.arraycopy(value, 0, dst, dstBegin << coder, value.length);
+        } else {    // this.coder == LATIN && coder == UTF16
+            StringLatin1.inflate(value, 0, dst, dstBegin, value.length);
+        }
+    }
+
+    /*
+     * Package private constructor. Trailing Void argument is there for
+     * disambiguating it against other (public) constructors.
+     *
+     * Stores the char[] value into a byte[] that each byte represents
+     * the8 low-order bits of the corresponding character, if the char[]
+     * contains only latin1 character. Or a byte[] that stores all
+     * characters in their byte sequences defined by the {@code StringUTF16}.
+     */
+    String(char[] value, int off, int len, Void sig) {
+        if (len == 0) {
+            this.value = "".value;
+            this.coder = "".coder;
+            return;
+        }
+        if (COMPACT_STRINGS) {
+            byte[] val = StringUTF16.compress(value, off, len);
+            if (val != null) {
+                this.value = val;
+                this.coder = LATIN1;
+                return;
+            }
+        }
+        this.coder = UTF16;
+        this.value = StringUTF16.toBytes(value, off, len);
+    }
+
+    /*
+     * Package private constructor. Trailing Void argument is there for
+     * disambiguating it against other (public) constructors.
+     */
+    String(AbstractStringBuilder asb, Void sig) {
+        byte[] val = asb.getValue();
+        int length = asb.length();
+        if (asb.isLatin1()) {
+            this.coder = LATIN1;
+            this.value = Arrays.copyOfRange(val, 0, length);
+        } else {
+            if (COMPACT_STRINGS) {
+                byte[] buf = StringUTF16.compress(val, 0, length);
+                if (buf != null) {
+                    this.coder = LATIN1;
+                    this.value = buf;
+                    return;
+                }
+            }
+            this.coder = UTF16;
+            this.value = Arrays.copyOfRange(val, 0, length << 1);
+        }
+    }
+
+   /*
+    * Package private constructor which shares value array for speed.
+    */
+    String(byte[] value, byte coder) {
+        this.value = value;
+        this.coder = coder;
+    }
+
+    byte coder() {
+        return COMPACT_STRINGS ? coder : UTF16;
+    }
+
+    private boolean isLatin1() {
+        return COMPACT_STRINGS && coder == LATIN1;
+    }
+
+    static final byte LATIN1 = 0;
+    static final byte UTF16  = 1;
+
+    /*
+     * StringIndexOutOfBoundsException  if {@code index} is
+     * negative or greater than or equal to {@code length}.
+     */
+    static void checkIndex(int index, int length) {
+        if (index < 0 || index >= length) {
+            throw new StringIndexOutOfBoundsException("index " + index);
+        }
+    }
+
+    /*
+     * StringIndexOutOfBoundsException  if {@code offset}
+     * is negative or greater than {@code length}.
+     */
+    static void checkOffset(int offset, int length) {
+        if (offset < 0 || offset > length) {
+            throw new StringIndexOutOfBoundsException("offset " + offset +
+                                                      ",length " + length);
+        }
+    }
+
+    /*
+     * Check {@code offset}, {@code count} against {@code 0} and {@code length}
+     * bounds.
+     *
+     * @throws  StringIndexOutOfBoundsException
+     *          If {@code offset} is negative, {@code count} is negative,
+     *          or {@code offset} is greater than {@code length - count}
+     */
+    private static void checkBoundsOffCount(int offset, int count, int length) {
+        if (offset < 0 || count < 0 || offset > length - count) {
+            throw new StringIndexOutOfBoundsException(
+                "offset " + offset + ", count " + count + ", length " + length);
+        }
+    }
+
+    /*
+     * Check {@code begin}, {@code end} against {@code 0} and {@code length}
+     * bounds.
+     *
+     * @throws  StringIndexOutOfBoundsException
+     *          If {@code begin} is negative, {@code begin} is greater than
+     *          {@code end}, or {@code end} is greater than {@code length}.
+     */
+    private static void checkBoundsBeginEnd(int begin, int end, int length) {
+        if (begin < 0 || begin > end || end > length) {
+            throw new StringIndexOutOfBoundsException(
+                "begin " + begin + ", end " + end + ", length " + length);
+        }
+    }
 }
--- a/jdk/src/java.base/share/classes/java/lang/StringBuffer.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/StringBuffer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -104,7 +104,7 @@
      * A cache of the last value returned by toString. Cleared
      * whenever the StringBuffer is modified.
      */
-    private transient char[] toStringCache;
+    private transient String toStringCache;
 
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     static final long serialVersionUID = 3388685877147921107L;
@@ -169,15 +169,13 @@
 
     @Override
     public synchronized int capacity() {
-        return value.length;
+        return super.capacity();
     }
 
 
     @Override
     public synchronized void ensureCapacity(int minimumCapacity) {
-        if (minimumCapacity > value.length) {
-            expandCapacity(minimumCapacity);
-        }
+        super.ensureCapacity(minimumCapacity);
     }
 
     /**
@@ -204,9 +202,7 @@
      */
     @Override
     public synchronized char charAt(int index) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
-        return value[index];
+        return super.charAt(index);
     }
 
     /**
@@ -261,10 +257,8 @@
      */
     @Override
     public synchronized void setCharAt(int index, char ch) {
-        if ((index < 0) || (index >= count))
-            throw new StringIndexOutOfBoundsException(index);
         toStringCache = null;
-        value[index] = ch;
+        super.setCharAt(index, ch);
     }
 
     @Override
@@ -680,9 +674,11 @@
     @HotSpotIntrinsicCandidate
     public synchronized String toString() {
         if (toStringCache == null) {
-            toStringCache = Arrays.copyOfRange(value, 0, count);
+            return toStringCache =
+                    isLatin1() ? StringLatin1.newString(value, 0, count)
+                               : StringUTF16.newString(value, 0, count);
         }
-        return new String(toStringCache, true);
+        return new String(toStringCache);
     }
 
     /**
@@ -710,7 +706,13 @@
     private synchronized void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
         java.io.ObjectOutputStream.PutField fields = s.putFields();
-        fields.put("value", value);
+        char[] val = new char[capacity()];
+        if (isLatin1()) {
+            StringLatin1.getChars(value, 0, count, val, 0);
+        } else {
+            StringUTF16.getChars(value, 0, count, val, 0);
+        }
+        fields.put("value", val);
         fields.put("count", count);
         fields.put("shared", false);
         s.writeFields();
@@ -723,7 +725,12 @@
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         java.io.ObjectInputStream.GetField fields = s.readFields();
-        value = (char[])fields.get("value", null);
+        char[] val = (char[])fields.get("value", null);
+        initBytes(val, 0, val.length);
         count = fields.get("count", 0);
     }
+
+    protected synchronized void getBytes(byte dst[], int dstBegin, byte coder) {
+        super.getBytes(dst, dstBegin, coder);
+    }
 }
--- a/jdk/src/java.base/share/classes/java/lang/StringBuilder.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/StringBuilder.java	Wed Jul 05 21:00:20 2017 +0200
@@ -412,7 +412,8 @@
     @HotSpotIntrinsicCandidate
     public String toString() {
         // Create a copy, don't share the array
-        return new String(value, 0, count);
+        return isLatin1() ? StringLatin1.newString(value, 0, count)
+                          : StringUTF16.newStringSB(value, 0, count);
     }
 
     /**
@@ -430,7 +431,13 @@
         throws java.io.IOException {
         s.defaultWriteObject();
         s.writeInt(count);
-        s.writeObject(value);
+        char[] val = new char[capacity()];
+        if (isLatin1()) {
+            StringLatin1.getChars(value, 0, count, val, 0);
+        } else {
+            StringUTF16.getChars(value, 0, count, val, 0);
+        }
+        s.writeObject(val);
     }
 
     /**
@@ -441,7 +448,8 @@
         throws java.io.IOException, ClassNotFoundException {
         s.defaultReadObject();
         count = s.readInt();
-        value = (char[]) s.readObject();
+        char[] val = (char[]) s.readObject();
+        initBytes(val, 0, val.length);
     }
 
 }
--- a/jdk/src/java.base/share/classes/java/lang/StringCoding.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/StringCoding.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,11 +38,19 @@
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.UnsupportedCharsetException;
 import java.util.Arrays;
+import jdk.internal.HotSpotIntrinsicCandidate;
 import sun.misc.MessageUtils;
 import sun.nio.cs.HistoricallyNamedCharset;
 import sun.nio.cs.ArrayDecoder;
 import sun.nio.cs.ArrayEncoder;
 
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+import static java.lang.String.COMPACT_STRINGS;
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 /**
  * Utility class for string encoding and decoding.
  */
@@ -72,23 +80,13 @@
 
     // Trim the given byte array to the given length
     //
-    private static byte[] safeTrim(byte[] ba, int len, Charset cs, boolean isTrusted) {
+    private static byte[] safeTrim(byte[] ba, int len, boolean isTrusted) {
         if (len == ba.length && (isTrusted || System.getSecurityManager() == null))
             return ba;
         else
             return Arrays.copyOf(ba, len);
     }
 
-    // Trim the given char array to the given length
-    //
-    private static char[] safeTrim(char[] ca, int len,
-                                   Charset cs, boolean isTrusted) {
-        if (len == ca.length && (isTrusted || System.getSecurityManager() == null))
-            return ca;
-        else
-            return Arrays.copyOf(ca, len);
-    }
-
     private static int scale(int len, float expansionFactor) {
         // We need to perform double, not float, arithmetic; otherwise
         // we lose low order bits when len is larger than 2**24.
@@ -117,21 +115,64 @@
         }
     }
 
+    static class Result {
+        byte[] value;
+        byte coder;
+
+        Result with() {
+            coder = COMPACT_STRINGS ? LATIN1 : UTF16;
+            value = new byte[0];
+            return this;
+        }
+
+        Result with(char[] val, int off, int len) {
+            if (String.COMPACT_STRINGS) {
+                byte[] bs = StringUTF16.compress(val, off, len);
+                if (bs != null) {
+                    value = bs;
+                    coder = LATIN1;
+                    return this;
+                }
+            }
+            coder = UTF16;
+            value = StringUTF16.toBytes(val, off, len);
+            return this;
+        }
+
+        Result with(byte[] val, byte coder) {
+            this.coder = coder;
+            value = val;
+            return this;
+        }
+    }
+
+    @HotSpotIntrinsicCandidate
+    private static boolean hasNegatives(byte[] ba, int off, int len) {
+        for (int i = off; i < off + len; i++) {
+            if (ba[i] < 0) {
+                return true;
+            }
+        }
+        return false;
+    }
 
     // -- Decoding --
-    private static class StringDecoder {
+    static class StringDecoder {
         private final String requestedCharsetName;
         private final Charset cs;
+        private final boolean isASCIICompatible;
         private final CharsetDecoder cd;
-        private final boolean isTrusted;
+        protected final Result result;
 
-        private StringDecoder(Charset cs, String rcn) {
+        StringDecoder(Charset cs, String rcn) {
             this.requestedCharsetName = rcn;
             this.cs = cs;
             this.cd = cs.newDecoder()
                 .onMalformedInput(CodingErrorAction.REPLACE)
                 .onUnmappableCharacter(CodingErrorAction.REPLACE);
-            this.isTrusted = (cs.getClass().getClassLoader0() == null);
+            this.result = new Result();
+            this.isASCIICompatible = (cd instanceof ArrayDecoder) &&
+                    ((ArrayDecoder)cd).isASCIICompatible();
         }
 
         String charsetName() {
@@ -144,36 +185,58 @@
             return requestedCharsetName;
         }
 
-        char[] decode(byte[] ba, int off, int len) {
+        Result decode(byte[] ba, int off, int len) {
+            if (len == 0) {
+                return result.with();
+            }
+            // fastpath for ascii compatible
+            if (isASCIICompatible && !hasNegatives(ba, off, len)) {
+                if (COMPACT_STRINGS) {
+                    return result.with(Arrays.copyOfRange(ba, off, off + len),
+                                      LATIN1);
+                } else {
+                    return result.with(StringLatin1.inflate(ba, off, len), UTF16);
+                }
+            }
             int en = scale(len, cd.maxCharsPerByte());
             char[] ca = new char[en];
-            if (len == 0)
-                return ca;
             if (cd instanceof ArrayDecoder) {
                 int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
-                return safeTrim(ca, clen, cs, isTrusted);
+                return result.with(ca, 0, clen);
+            }
+            cd.reset();
+            ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
+            CharBuffer cb = CharBuffer.wrap(ca);
+            try {
+                CoderResult cr = cd.decode(bb, cb, true);
+                if (!cr.isUnderflow())
+                    cr.throwException();
+                cr = cd.flush(cb);
+                if (!cr.isUnderflow())
+                    cr.throwException();
+            } catch (CharacterCodingException x) {
+                // Substitution is always enabled,
+                // so this shouldn't happen
+                throw new Error(x);
+            }
+            return result.with(ca, 0, cb.position());
+        }
+    }
+
+    private static class StringDecoder8859_1 extends StringDecoder {
+        StringDecoder8859_1(Charset cs, String rcn) {
+            super(cs, rcn);
+        }
+        Result decode(byte[] ba, int off, int len) {
+            if (COMPACT_STRINGS) {
+                return result.with(Arrays.copyOfRange(ba, off, off + len), LATIN1);
             } else {
-                cd.reset();
-                ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
-                CharBuffer cb = CharBuffer.wrap(ca);
-                try {
-                    CoderResult cr = cd.decode(bb, cb, true);
-                    if (!cr.isUnderflow())
-                        cr.throwException();
-                    cr = cd.flush(cb);
-                    if (!cr.isUnderflow())
-                        cr.throwException();
-                } catch (CharacterCodingException x) {
-                    // Substitution is always enabled,
-                    // so this shouldn't happen
-                    throw new Error(x);
-                }
-                return safeTrim(ca, cb.position(), cs, isTrusted);
+                return result.with(StringLatin1.inflate(ba, off, len), UTF16);
             }
         }
     }
 
-    static char[] decode(String charsetName, byte[] ba, int off, int len)
+    static Result decode(String charsetName, byte[] ba, int off, int len)
         throws UnsupportedEncodingException
     {
         StringDecoder sd = deref(decoder);
@@ -183,8 +246,15 @@
             sd = null;
             try {
                 Charset cs = lookupCharset(csn);
-                if (cs != null)
-                    sd = new StringDecoder(cs, csn);
+                if (cs != null) {
+                    if (cs == UTF_8) {
+                        sd = new StringDecoderUTF8(cs, csn);
+                    } else if (cs == ISO_8859_1) {
+                        sd = new StringDecoder8859_1(cs, csn);
+                    } else {
+                        sd = new StringDecoder(cs, csn);
+                    }
+                }
             } catch (IllegalCharsetNameException x) {}
             if (sd == null)
                 throw new UnsupportedEncodingException(csn);
@@ -193,7 +263,7 @@
         return sd.decode(ba, off, len);
     }
 
-    static char[] decode(Charset cs, byte[] ba, int off, int len) {
+    static Result decode(Charset cs, byte[] ba, int off, int len) {
         // (1)We never cache the "external" cs, the only benefit of creating
         // an additional StringDe/Encoder object to wrap it is to share the
         // de/encode() method. These SD/E objects are short-lived, the young-gen
@@ -210,44 +280,57 @@
         // check (... && (isTrusted || SM == null || getClassLoader0())) in trim
         // but it then can be argued that the SM is null when the operation
         // is started...
+        if (cs == UTF_8) {
+            return StringDecoderUTF8.decode(ba, off, len, new Result());
+        }
         CharsetDecoder cd = cs.newDecoder();
+        // ascii fastpath
+        if (cs == ISO_8859_1 || ((cd instanceof ArrayDecoder) &&
+                                 ((ArrayDecoder)cd).isASCIICompatible() &&
+                                 !hasNegatives(ba, off, len))) {
+             if (COMPACT_STRINGS) {
+                 return new Result().with(Arrays.copyOfRange(ba, off, off + len),
+                                          LATIN1);
+             } else {
+                 return new Result().with(StringLatin1.inflate(ba, off, len), UTF16);
+             }
+        }
         int en = scale(len, cd.maxCharsPerByte());
-        char[] ca = new char[en];
-        if (len == 0)
-            return ca;
-        boolean isTrusted = false;
-        if (System.getSecurityManager() != null) {
-            if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
-                ba =  Arrays.copyOfRange(ba, off, off + len);
-                off = 0;
-            }
+        if (len == 0) {
+            return new Result().with();
+        }
+        if (System.getSecurityManager() != null &&
+            cs.getClass().getClassLoader0() != null) {
+            ba =  Arrays.copyOfRange(ba, off, off + len);
+            off = 0;
         }
         cd.onMalformedInput(CodingErrorAction.REPLACE)
           .onUnmappableCharacter(CodingErrorAction.REPLACE)
           .reset();
+
+        char[] ca = new char[en];
         if (cd instanceof ArrayDecoder) {
             int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
-            return safeTrim(ca, clen, cs, isTrusted);
-        } else {
-            ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
-            CharBuffer cb = CharBuffer.wrap(ca);
-            try {
-                CoderResult cr = cd.decode(bb, cb, true);
-                if (!cr.isUnderflow())
-                    cr.throwException();
-                cr = cd.flush(cb);
-                if (!cr.isUnderflow())
-                    cr.throwException();
-            } catch (CharacterCodingException x) {
-                // Substitution is always enabled,
-                // so this shouldn't happen
-                throw new Error(x);
-            }
-            return safeTrim(ca, cb.position(), cs, isTrusted);
+            return new Result().with(ca, 0, clen);
         }
+        ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
+        CharBuffer cb = CharBuffer.wrap(ca);
+        try {
+            CoderResult cr = cd.decode(bb, cb, true);
+            if (!cr.isUnderflow())
+                cr.throwException();
+            cr = cd.flush(cb);
+            if (!cr.isUnderflow())
+                cr.throwException();
+        } catch (CharacterCodingException x) {
+            // Substitution is always enabled,
+            // so this shouldn't happen
+            throw new Error(x);
+        }
+        return new Result().with(ca, 0, cb.position());
     }
 
-    static char[] decode(byte[] ba, int off, int len) {
+    static Result decode(byte[] ba, int off, int len) {
         String csn = Charset.defaultCharset().name();
         try {
             // use charset name decode() variant which provides caching.
@@ -273,6 +356,7 @@
     private static class StringEncoder {
         private Charset cs;
         private CharsetEncoder ce;
+        private final boolean isASCIICompatible;
         private final String requestedCharsetName;
         private final boolean isTrusted;
 
@@ -283,6 +367,8 @@
                 .onMalformedInput(CodingErrorAction.REPLACE)
                 .onUnmappableCharacter(CodingErrorAction.REPLACE);
             this.isTrusted = (cs.getClass().getClassLoader0() == null);
+            this.isASCIICompatible = (ce instanceof ArrayEncoder) &&
+                    ((ArrayEncoder)ce).isASCIICompatible();
         }
 
         String charsetName() {
@@ -295,36 +381,186 @@
             return requestedCharsetName;
         }
 
-        byte[] encode(char[] ca, int off, int len) {
+        byte[] encode(byte coder, byte[] val) {
+            // fastpath for ascii compatible
+            if (coder == LATIN1 && isASCIICompatible &&
+                !hasNegatives(val, 0, val.length)) {
+                return Arrays.copyOf(val, val.length);
+            }
+            int len = val.length >> coder;  // assume LATIN1=0/UTF16=1;
             int en = scale(len, ce.maxBytesPerChar());
             byte[] ba = new byte[en];
-            if (len == 0)
+            if (len == 0) {
                 return ba;
+            }
             if (ce instanceof ArrayEncoder) {
-                int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
-                return safeTrim(ba, blen, cs, isTrusted);
-            } else {
-                ce.reset();
-                ByteBuffer bb = ByteBuffer.wrap(ba);
-                CharBuffer cb = CharBuffer.wrap(ca, off, len);
-                try {
-                    CoderResult cr = ce.encode(cb, bb, true);
-                    if (!cr.isUnderflow())
-                        cr.throwException();
-                    cr = ce.flush(bb);
-                    if (!cr.isUnderflow())
-                        cr.throwException();
-                } catch (CharacterCodingException x) {
-                    // Substitution is always enabled,
-                    // so this shouldn't happen
-                    throw new Error(x);
+                if (!isTrusted) {
+                    val = Arrays.copyOf(val, val.length);
+                }
+                int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
+                                              : ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
+                if (blen != -1) {
+                    return safeTrim(ba, blen, isTrusted);
                 }
-                return safeTrim(ba, bb.position(), cs, isTrusted);
             }
+            char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
+                                           : StringUTF16.toChars(val);
+            ce.reset();
+            ByteBuffer bb = ByteBuffer.wrap(ba);
+            CharBuffer cb = CharBuffer.wrap(ca, 0, len);
+            try {
+                CoderResult cr = ce.encode(cb, bb, true);
+                if (!cr.isUnderflow())
+                    cr.throwException();
+                cr = ce.flush(bb);
+                if (!cr.isUnderflow())
+                    cr.throwException();
+            } catch (CharacterCodingException x) {
+                // Substitution is always enabled,
+                // so this shouldn't happen
+                throw new Error(x);
+            }
+            return safeTrim(ba, bb.position(), isTrusted);
         }
     }
 
-    static byte[] encode(String charsetName, char[] ca, int off, int len)
+    @HotSpotIntrinsicCandidate
+    private static int implEncodeISOArray(byte[] sa, int sp,
+                                          byte[] da, int dp, int len) {
+        int i = 0;
+        for (; i < len; i++) {
+            char c = StringUTF16.getChar(sa, sp++);
+            if (c > '\u00FF')
+                break;
+            da[dp++] = (byte)c;
+        }
+        return i;
+    }
+
+    static byte[] encode8859_1(byte coder, byte[] val) {
+        if (coder == LATIN1) {
+            return Arrays.copyOf(val, val.length);
+        }
+        int len = val.length >> 1;
+        byte[] dst = new byte[len];
+        int dp = 0;
+        int sp = 0;
+        int sl = len;
+        while (sp < sl) {
+            int ret = implEncodeISOArray(val, sp, dst, dp, len);
+            sp = sp + ret;
+            dp = dp + ret;
+            if (ret != len) {
+                char c = StringUTF16.getChar(val, sp++);
+                if (Character.isHighSurrogate(c) && sp < sl &&
+                    Character.isLowSurrogate(StringUTF16.getChar(val, sp))) {
+                    sp++;
+                }
+                dst[dp++] = '?';
+                len = sl - sp;
+            }
+        }
+        if (dp == dst.length) {
+            return dst;
+        }
+        return Arrays.copyOf(dst, dp);
+    }
+
+    static byte[] encodeASCII(byte coder, byte[] val) {
+        if (coder == LATIN1) {
+            byte[] dst = new byte[val.length];
+            for (int i = 0; i < val.length; i++) {
+                if (val[i] < 0) {
+                    dst[i] = '?';
+                } else {
+                    dst[i] = val[i];
+                }
+            }
+            return dst;
+        }
+        int len = val.length >> 1;
+        byte[] dst = new byte[len];
+        int dp = 0;
+        for (int i = 0; i < len; i++) {
+            char c = StringUTF16.getChar(val, i);
+            if (c < 0x80) {
+                dst[dp++] = (byte)c;
+                continue;
+            }
+            if (Character.isHighSurrogate(c) && i + 1 < len &&
+                Character.isLowSurrogate(StringUTF16.getChar(val, i + 1))) {
+                i++;
+            }
+            dst[dp++] = '?';
+        }
+        if (len == dp) {
+            return dst;
+        }
+        return Arrays.copyOf(dst, dp);
+    }
+
+   static byte[] encodeUTF8(byte coder, byte[] val) {
+        int dp = 0;
+        byte[] dst;
+        if (coder == LATIN1) {
+            dst = new byte[val.length << 1];
+            for (int sp = 0; sp < val.length; sp++) {
+                byte c = val[sp];
+                if (c < 0) {
+                    dst[dp++] = (byte)(0xc0 | ((c & 0xff) >> 6));
+                    dst[dp++] = (byte)(0x80 | (c & 0x3f));
+                } else {
+                    dst[dp++] = c;
+                }
+            }
+        } else {
+            int sp = 0;
+            int sl = val.length >> 1;
+            dst = new byte[sl * 3];
+            char c;
+            while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') {
+                // ascii fast loop;
+                dst[dp++] = (byte)c;
+                sp++;
+            }
+            while (sp < sl) {
+                c = StringUTF16.getChar(val, sp++);
+                if (c < 0x80) {
+                    dst[dp++] = (byte)c;
+                } else if (c < 0x800) {
+                    dst[dp++] = (byte)(0xc0 | (c >> 6));
+                    dst[dp++] = (byte)(0x80 | (c & 0x3f));
+                } else if (Character.isSurrogate(c)) {
+                    int uc = -1;
+                    char c2;
+                    if (Character.isHighSurrogate(c) && sp < sl &&
+                        Character.isLowSurrogate(c2 = StringUTF16.getChar(val, sp))) {
+                        uc = Character.toCodePoint(c, c2);
+                    }
+                    if (uc < 0) {
+                        dst[dp++] = '?';
+                    } else {
+                        dst[dp++] = (byte)(0xf0 | ((uc >> 18)));
+                        dst[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
+                        dst[dp++] = (byte)(0x80 | ((uc >>  6) & 0x3f));
+                        dst[dp++] = (byte)(0x80 | (uc & 0x3f));
+                        sp++;  // 2 chars
+                    }
+                } else {
+                    // 3 bytes, 16 bits
+                    dst[dp++] = (byte)(0xe0 | ((c >> 12)));
+                    dst[dp++] = (byte)(0x80 | ((c >>  6) & 0x3f));
+                    dst[dp++] = (byte)(0x80 | (c & 0x3f));
+                }
+            }
+        }
+        if (dp == dst.length) {
+            return dst;
+        }
+        return Arrays.copyOf(dst, dp);
+    }
+
+    static byte[] encode(String charsetName, byte coder, byte[] val)
         throws UnsupportedEncodingException
     {
         StringEncoder se = deref(encoder);
@@ -334,62 +570,88 @@
             se = null;
             try {
                 Charset cs = lookupCharset(csn);
-                if (cs != null)
+                if (cs != null) {
+                    if (cs == UTF_8) {
+                        return encodeUTF8(coder, val);
+                    } else if (cs == ISO_8859_1) {
+                        return encode8859_1(coder, val);
+                    } else if (cs == US_ASCII) {
+                        return encodeASCII(coder, val);
+                    }
                     se = new StringEncoder(cs, csn);
+                }
             } catch (IllegalCharsetNameException x) {}
-            if (se == null)
+            if (se == null) {
                 throw new UnsupportedEncodingException (csn);
+            }
             set(encoder, se);
         }
-        return se.encode(ca, off, len);
+        return se.encode(coder, val);
     }
 
-    static byte[] encode(Charset cs, char[] ca, int off, int len) {
+    static byte[] encode(Charset cs, byte coder, byte[] val) {
+        if (cs == UTF_8) {
+            return encodeUTF8(coder, val);
+        } else if (cs == ISO_8859_1) {
+            return encode8859_1(coder, val);
+        } else if (cs == US_ASCII) {
+            return encodeASCII(coder, val);
+        }
         CharsetEncoder ce = cs.newEncoder();
+        // fastpath for ascii compatible
+        if (coder == LATIN1 && (((ce instanceof ArrayEncoder) &&
+                                 ((ArrayEncoder)ce).isASCIICompatible() &&
+                                 !hasNegatives(val, 0, val.length)))) {
+            return Arrays.copyOf(val, val.length);
+        }
+        int len = val.length >> coder;  // assume LATIN1=0/UTF16=1;
         int en = scale(len, ce.maxBytesPerChar());
         byte[] ba = new byte[en];
-        if (len == 0)
+        if (len == 0) {
             return ba;
-        boolean isTrusted = false;
-        if (System.getSecurityManager() != null) {
-            if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
-                ca =  Arrays.copyOfRange(ca, off, off + len);
-                off = 0;
-            }
         }
+        boolean isTrusted = System.getSecurityManager() == null ||
+                            cs.getClass().getClassLoader0() == null;
         ce.onMalformedInput(CodingErrorAction.REPLACE)
           .onUnmappableCharacter(CodingErrorAction.REPLACE)
           .reset();
         if (ce instanceof ArrayEncoder) {
-            int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
-            return safeTrim(ba, blen, cs, isTrusted);
-        } else {
-            ByteBuffer bb = ByteBuffer.wrap(ba);
-            CharBuffer cb = CharBuffer.wrap(ca, off, len);
-            try {
-                CoderResult cr = ce.encode(cb, bb, true);
-                if (!cr.isUnderflow())
-                    cr.throwException();
-                cr = ce.flush(bb);
-                if (!cr.isUnderflow())
-                    cr.throwException();
-            } catch (CharacterCodingException x) {
-                throw new Error(x);
+            if (!isTrusted) {
+                val = Arrays.copyOf(val, val.length);
+            }
+            int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
+                                          : ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
+            if (blen != -1) {
+                return safeTrim(ba, blen, isTrusted);
             }
-            return safeTrim(ba, bb.position(), cs, isTrusted);
         }
+        char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
+                                       : StringUTF16.toChars(val);
+        ByteBuffer bb = ByteBuffer.wrap(ba);
+        CharBuffer cb = CharBuffer.wrap(ca, 0, len);
+        try {
+            CoderResult cr = ce.encode(cb, bb, true);
+            if (!cr.isUnderflow())
+                cr.throwException();
+            cr = ce.flush(bb);
+            if (!cr.isUnderflow())
+                cr.throwException();
+        } catch (CharacterCodingException x) {
+            throw new Error(x);
+        }
+        return safeTrim(ba, bb.position(), isTrusted);
     }
 
-    static byte[] encode(char[] ca, int off, int len) {
+    static byte[] encode(byte coder, byte[] val) {
         String csn = Charset.defaultCharset().name();
         try {
             // use charset name encode() variant which provides caching.
-            return encode(csn, ca, off, len);
+            return encode(csn, coder, val);
         } catch (UnsupportedEncodingException x) {
             warnUnsupportedCharset(csn);
         }
         try {
-            return encode("ISO-8859-1", ca, off, len);
+            return encode("ISO-8859-1", coder, val);
         } catch (UnsupportedEncodingException x) {
             // If this code is hit during VM initialization, MessageUtils is
             // the only way we will be able to get any kind of error message.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/StringDecoderUTF8.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.Character.isSurrogate;
+import static java.lang.Character.highSurrogate;
+import static java.lang.Character.lowSurrogate;
+import static java.lang.Character.isSupplementaryCodePoint;
+import static java.lang.StringUTF16.putChar;
+
+class StringDecoderUTF8 extends StringCoding.StringDecoder {
+
+    StringDecoderUTF8(Charset cs, String rcn) {
+        super(cs, rcn);
+    }
+
+    private static boolean isNotContinuation(int b) {
+        return (b & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed3(int b1, int b2, int b3) {
+        return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+               (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed3_2(int b1, int b2) {
+        return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+               (b2 & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed4(int b2, int b3, int b4) {
+        return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
+               (b4 & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed4_2(int b1, int b2) {
+        return (b1 == 0xf0 && (b2  < 0x90 || b2 > 0xbf)) ||
+               (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
+               (b2 & 0xc0) != 0x80;
+    }
+
+    private static boolean isMalformed4_3(int b3) {
+        return (b3 & 0xc0) != 0x80;
+    }
+
+    // for nb == 3/4
+    private static int malformedN(byte[] src, int sp, int nb) {
+        if (nb == 3) {
+            int b1 = src[sp++];
+            int b2 = src[sp++];    // no need to lookup b3
+            return ((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+                    isNotContinuation(b2)) ? 1 : 2;
+        } else if (nb == 4) { // we don't care the speed here
+            int b1 = src[sp++] & 0xff;
+            int b2 = src[sp++] & 0xff;
+            if (b1 > 0xf4 ||
+                (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
+                (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
+                isNotContinuation(b2))
+                return 1;
+            if (isNotContinuation(src[sp++]))
+                return 2;
+            return 3;
+        }
+        assert false;
+        return -1;
+    }
+
+    private static char repl = '\ufffd';
+
+    StringCoding.Result decode(byte[] src, int sp, int len) {
+        return decode(src, sp, len, result);
+    }
+
+    static StringCoding.Result decode(byte[] src, int sp, int len,
+                                      StringCoding.Result ret) {
+        int sl = sp + len;
+        byte[] dst = new byte[len];
+        int dp = 0;
+        if (COMPACT_STRINGS) {   // Latin1 only loop
+            while (sp < sl) {
+                int b1 = src[sp];
+                if (b1 >= 0) {
+                    dst[dp++] = (byte)b1;
+                    sp++;
+                    continue;
+                }
+                if ((b1 == (byte)0xc2 || b1 == (byte)0xc3) &&
+                    sp + 1 < sl) {
+                    int b2 = src[sp + 1];
+                    if (!isNotContinuation(b2)) {
+                        dst[dp++] = (byte)(((b1 << 6) ^ b2)^
+                                           (((byte) 0xC0 << 6) ^
+                                           ((byte) 0x80 << 0)));
+                        sp += 2;
+                        continue;
+                    }
+                }
+                // anything not a latin1, including the repl
+                // we have to go with the utf16
+                break;
+            }
+            if (sp == sl) {
+                if (dp != dst.length) {
+                    dst = Arrays.copyOf(dst, dp);
+                }
+                return ret.with(dst, LATIN1);
+            }
+        }
+        if (dp == 0) {
+            dst = new byte[len << 1];
+        } else {
+            byte[] buf = new byte[len << 1];
+            StringLatin1.inflate(dst, 0, buf, 0, dp);
+            dst = buf;
+        }
+        while (sp < sl) {
+            int b1 = src[sp++];
+            if (b1 >= 0) {
+                putChar(dst, dp++, (char) b1);
+            } else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
+                if (sp < sl) {
+                    int b2 = src[sp++];
+                    if (isNotContinuation(b2)) {
+                        putChar(dst, dp++, repl);
+                        sp--;
+                    } else {
+                        putChar(dst, dp++, (char)(((b1 << 6) ^ b2)^
+                                                  (((byte) 0xC0 << 6) ^
+                                                  ((byte) 0x80 << 0))));
+                    }
+                    continue;
+                }
+                putChar(dst, dp++, repl);
+                break;
+            } else if ((b1 >> 4) == -2) {
+                if (sp + 1 < sl) {
+                    int b2 = src[sp++];
+                    int b3 = src[sp++];
+                    if (isMalformed3(b1, b2, b3)) {
+                        putChar(dst, dp++, repl);
+                        sp -= 3;
+                        sp += malformedN(src, sp, 3);
+                    } else {
+                        char c = (char)((b1 << 12) ^
+                                        (b2 <<  6) ^
+                                        (b3 ^
+                                         (((byte) 0xE0 << 12) ^
+                                         ((byte) 0x80 <<  6) ^
+                                         ((byte) 0x80 <<  0))));
+                        putChar(dst, dp++, isSurrogate(c) ?  repl : c);
+                    }
+                    continue;
+                }
+                if (sp  < sl && isMalformed3_2(b1, src[sp])) {
+                    putChar(dst, dp++, repl);
+                    continue;
+                }
+                putChar(dst, dp++, repl);
+                break;
+            } else if ((b1 >> 3) == -2) {
+                if (sp + 2 < sl) {
+                    int b2 = src[sp++];
+                    int b3 = src[sp++];
+                    int b4 = src[sp++];
+                    int uc = ((b1 << 18) ^
+                              (b2 << 12) ^
+                              (b3 <<  6) ^
+                              (b4 ^
+                               (((byte) 0xF0 << 18) ^
+                               ((byte) 0x80 << 12) ^
+                               ((byte) 0x80 <<  6) ^
+                               ((byte) 0x80 <<  0))));
+                    if (isMalformed4(b2, b3, b4) ||
+                        !isSupplementaryCodePoint(uc)) { // shortest form check
+                        putChar(dst, dp++, repl);
+                        sp -= 4;
+                        sp += malformedN(src, sp, 4);
+                    } else {
+                        putChar(dst, dp++, highSurrogate(uc));
+                        putChar(dst, dp++, lowSurrogate(uc));
+                    }
+                    continue;
+                }
+                b1 &= 0xff;
+                if (b1 > 0xf4 ||
+                    sp  < sl && isMalformed4_2(b1, src[sp] & 0xff)) {
+                    putChar(dst, dp++, repl);
+                    continue;
+                }
+                sp++;
+                putChar(dst, dp++, repl);
+                if (sp  < sl && isMalformed4_3(src[sp])) {
+                    continue;
+                }
+                break;
+            } else {
+                putChar(dst, dp++, repl);
+            }
+        }
+        if (dp != len) {
+            dst = Arrays.copyOf(dst, dp << 1);
+        }
+        return ret.with(dst, UTF16);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Spliterator;
+import java.util.function.IntConsumer;
+import java.util.stream.IntStream;
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+import static java.lang.String.LATIN1;
+import static java.lang.String.UTF16;
+import static java.lang.String.checkOffset;
+
+final class StringLatin1 {
+
+    public static char charAt(byte[] value, int index) {
+        if (index < 0 || index >= value.length) {
+            throw new StringIndexOutOfBoundsException(index);
+        }
+        return (char)(value[index] & 0xff);
+    }
+
+    public static boolean canEncode(int cp) {
+        return cp >>> 8 == 0;
+    }
+
+    public static int length(byte[] value) {
+        return value.length;
+    }
+
+    public static int codePointAt(byte[] value, int index, int end) {
+        return value[index] & 0xff;
+    }
+
+    public static int codePointBefore(byte[] value, int index) {
+        return value[index - 1] & 0xff;
+    }
+
+    public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
+        return endIndex - beginIndex;
+    }
+
+    public static char[] toChars(byte[] value) {
+        char[] dst = new char[value.length];
+        inflate(value, 0, dst, 0, value.length);
+        return dst;
+    }
+
+    public static byte[] inflate(byte[] value, int off, int len) {
+        byte[] ret = StringUTF16.newBytesFor(len);
+        inflate(value, off, ret, 0, len);
+        return ret;
+    }
+
+    public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
+        inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
+    }
+
+    public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
+        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static boolean equals(byte[] value, byte[] other) {
+        if (value.length == other.length) {
+            for (int i = 0; i < value.length; i++) {
+                if (value[i] != other[i]) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int compareTo(byte[] value, byte[] other) {
+        int len1 = value.length;
+        int len2 = other.length;
+        int lim = Math.min(len1, len2);
+        for (int k = 0; k < lim; k++) {
+            if (value[k] != other[k]) {
+                return getChar(value, k) - getChar(other, k);
+            }
+        }
+        return len1 - len2;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int compareToUTF16(byte[] value, byte[] other) {
+        int len1 = length(value);
+        int len2 = StringUTF16.length(other);
+        int lim = Math.min(len1, len2);
+        for (int k = 0; k < lim; k++) {
+            char c1 = getChar(value, k);
+            char c2 = StringUTF16.getChar(other, k);
+            if (c1 != c2) {
+                return c1 - c2;
+            }
+        }
+        return len1 - len2;
+    }
+
+    public static int hashCode(byte[] value) {
+        int h = 0;
+        for (byte v : value) {
+            h = 31 * h + (v & 0xff);
+        }
+        return h;
+    }
+
+    public static int indexOf(byte[] value, int ch, int fromIndex) {
+        if (!canEncode(ch)) {
+            return -1;
+        }
+        int max = value.length;
+        if (fromIndex < 0) {
+            fromIndex = 0;
+        } else if (fromIndex >= max) {
+            // Note: fromIndex might be near -1>>>1.
+            return -1;
+        }
+        byte c = (byte)ch;
+        for (int i = fromIndex; i < max; i++) {
+            if (value[i] == c) {
+               return i;
+            }
+        }
+        return -1;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOf(byte[] value, byte[] str) {
+        if (str.length == 0) {
+            return 0;
+        }
+        if (value.length == 0) {
+            return -1;
+        }
+        return indexOf(value, value.length, str, str.length, 0);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
+        byte first = str[0];
+        int max = (valueCount - strCount);
+        for (int i = fromIndex; i <= max; i++) {
+            // Look for first character.
+            if (value[i] != first) {
+                while (++i <= max && value[i] != first);
+            }
+            // Found first character, now look at the rest of value
+            if (i <= max) {
+                int j = i + 1;
+                int end = j + strCount - 1;
+                for (int k = 1; j < end && value[j] == str[k]; j++, k++);
+                if (j == end) {
+                    // Found whole string.
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    public static int lastIndexOf(byte[] src, int srcCount,
+                                  byte[] tgt, int tgtCount, int fromIndex) {
+        int min = tgtCount - 1;
+        int i = min + fromIndex;
+        int strLastIndex = tgtCount - 1;
+        char strLastChar = (char)(tgt[strLastIndex] & 0xff);
+
+  startSearchForLastChar:
+        while (true) {
+            while (i >= min && (src[i] & 0xff) != strLastChar) {
+                i--;
+            }
+            if (i < min) {
+                return -1;
+            }
+            int j = i - 1;
+            int start = j - strLastIndex;
+            int k = strLastIndex - 1;
+            while (j > start) {
+                if ((src[j--] & 0xff) != (tgt[k--] & 0xff)) {
+                    i--;
+                    continue startSearchForLastChar;
+                }
+            }
+            return start + 1;
+        }
+    }
+
+    public static int lastIndexOf(final byte[] value, int ch, int fromIndex) {
+        if (!canEncode(ch)) {
+            return -1;
+        }
+        int off  = Math.min(fromIndex, value.length - 1);
+        for (; off >= 0; off--) {
+            if (value[off] == (byte)ch) {
+                return off;
+            }
+        }
+        return -1;
+    }
+
+    public static String replace(byte[] value, char oldChar, char newChar) {
+        if (canEncode(oldChar)) {
+            int len = value.length;
+            int i = -1;
+            while (++i < len) {
+                if (value[i] == (byte)oldChar) {
+                    break;
+                }
+            }
+            if (i < len) {
+                if (canEncode(newChar)) {
+                    byte buf[] = new byte[len];
+                    for (int j = 0; j < i; j++) {    // TBD arraycopy?
+                        buf[j] = value[j];
+                    }
+                    while (i < len) {
+                        byte c = value[i];
+                        buf[i] = (c == (byte)oldChar) ? (byte)newChar : c;
+                        i++;
+                    }
+                    return new String(buf, LATIN1);
+                } else {
+                    byte[] buf = StringUTF16.newBytesFor(len);
+                    // inflate from latin1 to UTF16
+                    inflate(value, 0, buf, 0, i);
+                    while (i < len) {
+                        char c = (char)(value[i] & 0xff);
+                        StringUTF16.putChar(buf, i, (c == oldChar) ? newChar : c);
+                        i++;
+                    }
+                    return new String(buf, UTF16);
+                }
+            }
+        }
+        return null; // for string to return this;
+    }
+
+    // case insensitive
+    public static boolean regionMatchesCI(byte[] value, int toffset,
+                                          byte[] other, int ooffset, int len) {
+        int last = toffset + len;
+        while (toffset < last) {
+            char c1 = (char)(value[toffset++] & 0xff);
+            char c2 = (char)(other[ooffset++] & 0xff);
+            if (c1 == c2) {
+                continue;
+            }
+            char u1 = Character.toUpperCase(c1);
+            char u2 = Character.toUpperCase(c2);
+            if (u1 == u2) {
+                continue;
+            }
+            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean regionMatchesCI_UTF16(byte[] value, int toffset,
+                                                byte[] other, int ooffset, int len) {
+        int last = toffset + len;
+        while (toffset < last) {
+            char c1 = (char)(value[toffset++] & 0xff);
+            char c2 = StringUTF16.getChar(other, ooffset++);
+            if (c1 == c2) {
+                continue;
+            }
+            char u1 = Character.toUpperCase(c1);
+            char u2 = Character.toUpperCase(c2);
+            if (u1 == u2) {
+                continue;
+            }
+            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public static String toLowerCase(String str, byte[] value, Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException();
+        }
+        int first;
+        final int len = value.length;
+        // Now check if there are any characters that need to be changed, or are surrogate
+        for (first = 0 ; first < len; first++) {
+            int cp = value[first] & 0xff;
+            if (cp != Character.toLowerCase(cp)) {  // no need to check Character.ERROR
+                break;
+            }
+        }
+        if (first == len)
+            return str;
+        String lang = locale.getLanguage();
+        if (lang == "tr" || lang == "az" || lang == "lt") {
+            return toLowerCaseEx(str, value, first, locale, true);
+        }
+        byte[] result = new byte[len];
+        System.arraycopy(value, 0, result, 0, first);  // Just copy the first few
+                                                       // lowerCase characters.
+        for (int i = first; i < len; i++) {
+            int cp = value[i] & 0xff;
+            cp = Character.toLowerCase(cp);
+            if (!canEncode(cp)) {                      // not a latin1 character
+                return toLowerCaseEx(str, value, first, locale, false);
+            }
+            result[i] = (byte)cp;
+        }
+        return new String(result, LATIN1);
+    }
+
+    private static String toLowerCaseEx(String str, byte[] value,
+                                        int first, Locale locale, boolean localeDependent)
+    {
+        byte[] result = StringUTF16.newBytesFor(value.length);
+        int resultOffset = 0;
+        for (int i = 0; i < first; i++) {
+            StringUTF16.putChar(result, resultOffset++, value[i] & 0xff);
+        }
+        for (int i = first; i < value.length; i++) {
+            int srcChar = value[i] & 0xff;
+            int lowerChar;
+            char[] lowerCharArray;
+            if (localeDependent) {
+                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
+            } else {
+                lowerChar = Character.toLowerCase(srcChar);
+            }
+            if (Character.isBmpCodePoint(lowerChar)) {    // Character.ERROR is not a bmp
+                StringUTF16.putChar(result, resultOffset++, lowerChar);
+            } else {
+                if (lowerChar == Character.ERROR) {
+                    lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
+                } else {
+                    lowerCharArray = Character.toChars(lowerChar);
+                }
+                /* Grow result if needed */
+                int mapLen = lowerCharArray.length;
+                if (mapLen > 1) {
+                    byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1);
+                    System.arraycopy(result, 0, result2, 0, resultOffset << 1);
+                    result = result2;
+                }
+                for (int x = 0; x < mapLen; ++x) {
+                    StringUTF16.putChar(result, resultOffset++, lowerCharArray[x]);
+                }
+            }
+        }
+        return StringUTF16.newString(result, 0, resultOffset);
+    }
+
+    public static String toUpperCase(String str, byte[] value, Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException();
+        }
+        int first;
+        final int len = value.length;
+
+        // Now check if there are any characters that need to be changed, or are surrogate
+        for (first = 0 ; first < len; first++ ) {
+            int cp = value[first] & 0xff;
+            if (cp != Character.toUpperCaseEx(cp)) {   // no need to check Character.ERROR
+                break;
+            }
+        }
+        if (first == len) {
+            return str;
+        }
+        String lang = locale.getLanguage();
+        if (lang == "tr" || lang == "az" || lang == "lt") {
+            return toUpperCaseEx(str, value, first, locale, true);
+        }
+        byte[] result = new byte[len];
+        System.arraycopy(value, 0, result, 0, first);  // Just copy the first few
+                                                       // upperCase characters.
+        for (int i = first; i < len; i++) {
+            int cp = value[i] & 0xff;
+            cp = Character.toUpperCaseEx(cp);
+            if (!canEncode(cp)) {                      // not a latin1 character
+                return toUpperCaseEx(str, value, first, locale, false);
+            }
+            result[i] = (byte)cp;
+        }
+        return new String(result, LATIN1);
+    }
+
+    private static String toUpperCaseEx(String str, byte[] value,
+                                        int first, Locale locale, boolean localeDependent)
+    {
+        byte[] result = StringUTF16.newBytesFor(value.length);
+        int resultOffset = 0;
+        for (int i = 0; i < first; i++) {
+            StringUTF16.putChar(result, resultOffset++, value[i] & 0xff);
+        }
+        for (int i = first; i < value.length; i++) {
+            int srcChar = value[i] & 0xff;
+            int upperChar;
+            char[] upperCharArray;
+            if (localeDependent) {
+                upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
+            } else {
+                upperChar = Character.toUpperCaseEx(srcChar);
+            }
+            if (Character.isBmpCodePoint(upperChar)) {
+                StringUTF16.putChar(result, resultOffset++, upperChar);
+            } else {
+                if (upperChar == Character.ERROR) {
+                    if (localeDependent) {
+                        upperCharArray =
+                            ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
+                    } else {
+                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
+                    }
+                } else {
+                    upperCharArray = Character.toChars(upperChar);
+                }
+                /* Grow result if needed */
+                int mapLen = upperCharArray.length;
+                if (mapLen > 1) {
+                    byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1);
+                    System.arraycopy(result, 0, result2, 0, resultOffset << 1);
+                    result = result2;
+                }
+                for (int x = 0; x < mapLen; ++x) {
+                    StringUTF16.putChar(result, resultOffset++, upperCharArray[x]);
+                }
+            }
+        }
+        return StringUTF16.newString(result, 0, resultOffset);
+    }
+
+    public static String trim(byte[] value) {
+        int len = value.length;
+        int st = 0;
+        while ((st < len) && ((value[st] & 0xff) <= ' ')) {
+            st++;
+        }
+        while ((st < len) && ((value[len - 1] & 0xff) <= ' ')) {
+            len--;
+        }
+        return ((st > 0) || (len < value.length)) ?
+            newString(value, st, len - st) : null;
+    }
+
+    public static void putChar(byte[] val, int index, int c) {
+        //assert (canEncode(c));
+        val[index] = (byte)(c);
+    }
+
+    public static char getChar(byte[] val, int index) {
+        return (char)(val[index] & 0xff);
+    }
+
+    public static byte[] toBytes(int[] val, int off, int len) {
+        byte[] ret = new byte[len];
+        for (int i = 0; i < len; i++) {
+            int cp = val[off++];
+            if (!canEncode(cp)) {
+                return null;
+            }
+            ret[i] = (byte)cp;
+        }
+        return ret;
+    }
+
+    public static byte[] toBytes(char c) {
+        return new byte[] { (byte)c };
+    }
+
+    public static String newString(byte[] val, int index, int len) {
+        return new String(Arrays.copyOfRange(val, index, index + len),
+                          LATIN1);
+    }
+
+    public static void fillNull(byte[] val, int index, int end) {
+        Arrays.fill(val, index, end, (byte)0);
+    }
+
+    // inflatedCopy byte[] -> char[]
+    @HotSpotIntrinsicCandidate
+    private static void inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
+        for (int i = 0; i < len; i++) {
+            dst[dstOff++] = (char)(src[srcOff++] & 0xff);
+        }
+    }
+
+    // inflatedCopy byte[] -> byte[]
+    @HotSpotIntrinsicCandidate
+    public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
+        for (int i = 0; i < len; i++) {
+            StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff);
+        }
+    }
+
+    static class CharsSpliterator implements Spliterator.OfInt {
+        private final byte[] array;
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        CharsSpliterator(byte[] array, int acs) {
+            this(array, 0, array.length, acs);
+        }
+
+        CharsSpliterator(byte[] array, int origin, int fence, int acs) {
+            this.array = array;
+            this.index = origin;
+            this.fence = fence;
+            this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
+                      | Spliterator.SUBSIZED;
+        }
+
+        @Override
+        public OfInt trySplit() {
+            int lo = index, mid = (lo + fence) >>> 1;
+            return (lo >= mid)
+                   ? null
+                   : new CharsSpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            byte[] a; int i, hi; // hoist accesses and checks from loop
+            if (action == null)
+                throw new NullPointerException();
+            if ((a = array).length >= (hi = fence) &&
+                (i = index) >= 0 && i < (index = hi)) {
+                do { action.accept(a[i] & 0xff); } while (++i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (index >= 0 && index < fence) {
+                action.accept(array[index++] & 0xff);
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////
+
+    public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
+        checkOffset(srcEnd, val.length);
+        getChars(val, srcBegin, srcEnd, dst, dstBegin);
+    }
+
+    public static void inflateSB(byte[] val, byte[] dst, int dstOff, int count) {
+        checkOffset(count, val.length);
+        checkOffset(dstOff + count, dst.length >> 1);  // dst is utf16
+        inflate(val, 0, dst, dstOff, count);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,971 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Spliterator;
+import java.util.function.IntConsumer;
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+import static java.lang.String.UTF16;
+import static java.lang.String.LATIN1;
+import static java.lang.String.checkIndex;
+import static java.lang.String.checkOffset;
+
+final class StringUTF16 {
+
+    public static byte[] newBytesFor(int len) {
+        if (len < 0) {
+            throw new NegativeArraySizeException();
+        }
+        if (len > MAX_LENGTH) {
+            throw new OutOfMemoryError("UTF16 String size is " + len +
+                                       ", should be less than " + MAX_LENGTH);
+        }
+        return new byte[len << 1];
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static void putChar(byte[] val, int index, int c) {
+        index <<= 1;
+        val[index++] = (byte)(c >> HI_BYTE_SHIFT);
+        val[index]   = (byte)(c >> LO_BYTE_SHIFT);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static char getChar(byte[] val, int index) {
+        index <<= 1;
+        return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
+                      ((val[index]   & 0xff) << LO_BYTE_SHIFT));
+    }
+
+    public static char charAt(byte[] value, int index) {
+        if (index < 0 || index >= value.length >> 1) {
+            throw new StringIndexOutOfBoundsException(index);
+        }
+        return getChar(value, index);
+    }
+
+    public static int length(byte[] value) {
+        return value.length >> 1;
+    }
+
+    public static int codePointAt(byte[] value, int index, int end) {
+        char c1 = getChar(value, index);
+        if (Character.isHighSurrogate(c1) && ++index < end) {
+            char c2 = getChar(value, index);
+            if (Character.isLowSurrogate(c2)) {
+               return Character.toCodePoint(c1, c2);
+            }
+        }
+        return c1;
+    }
+
+    public static int codePointBefore(byte[] value, int index) {
+        char c2 = getChar(value, --index);
+        if (Character.isLowSurrogate(c2) && index > 0) {
+            char c1 = getChar(value, --index);
+            if (Character.isHighSurrogate(c1)) {
+               return Character.toCodePoint(c1, c2);
+            }
+        }
+        return c2;
+    }
+
+    public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
+        int count = endIndex - beginIndex;
+        for (int i = beginIndex; i < endIndex; ) {
+            if (Character.isHighSurrogate(getChar(value, i++)) &&
+                i < endIndex &&
+                Character.isLowSurrogate(getChar(value, i))) {
+                count--;
+                i++;
+            }
+        }
+        return count;
+    }
+
+    public static char[] toChars(byte[] value) {
+        char[] dst = new char[value.length >> 1];
+        getChars(value, 0, dst.length, dst, 0);
+        return dst;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static byte[] toBytes(char[] value, int off, int len) {
+        byte[] val = newBytesFor(len);
+        for (int i = 0; i < len; i++) {
+            putChar(val, i, value[off++]);
+        }
+        return val;
+    }
+
+    public static byte[] compress(char[] val, int off, int len) {
+        byte[] ret = new byte[len];
+        if (compress(val, off, ret, 0, len) == len) {
+            return ret;
+        }
+        return null;
+    }
+
+    public static byte[] compress(byte[] val, int off, int len) {
+        byte[] ret = new byte[len];
+        if (compress(val, off, ret, 0, len) == len) {
+            return ret;
+        }
+        return null;
+    }
+
+    // compressedCopy char[] -> byte[]
+    @HotSpotIntrinsicCandidate
+    private static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
+        for (int i = 0; i < len; i++) {
+            int c = src[srcOff++];
+            if (c >>> 8 != 0) {
+                return 0;
+            }
+            dst[dstOff++] = (byte)c;
+        }
+        return len;
+    }
+
+    // compressedCopy byte[] -> byte[]
+    @HotSpotIntrinsicCandidate
+    public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
+        for (int i = 0; i < len; i++) {
+            int c = getChar(src, srcOff++);
+            if (c >>> 8 != 0) {
+                return 0;
+            }
+            dst[dstOff++] = (byte)c;
+        }
+        return len;
+    }
+
+    public static byte[] toBytes(int[] val, int index, int len) {
+        final int end = index + len;
+        // Pass 1: Compute precise size of char[]
+        int n = len;
+        for (int i = index; i < end; i++) {
+            int cp = val[i];
+            if (Character.isBmpCodePoint(cp))
+                continue;
+            else if (Character.isValidCodePoint(cp))
+                n++;
+            else throw new IllegalArgumentException(Integer.toString(cp));
+        }
+        // Pass 2: Allocate and fill in <high, low> pair
+        byte[] buf = newBytesFor(n);
+        for (int i = index, j = 0; i < end; i++, j++) {
+            int cp = val[i];
+            if (Character.isBmpCodePoint(cp)) {
+                putChar(buf, j, cp);
+            } else {
+                putChar(buf, j++, Character.highSurrogate(cp));
+                putChar(buf, j, Character.lowSurrogate(cp));
+            }
+        }
+        return buf;
+    }
+
+    public static byte[] toBytes(char c) {
+        byte[] result = new byte[2];
+        putChar(result, 0, c);
+        return result;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
+        for (int i = srcBegin; i < srcEnd; i++) {
+            dst[dstBegin++] = getChar(value, i);
+        }
+    }
+
+    /* @see java.lang.String.getBytes(int, int, byte[], int) */
+    public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
+        srcBegin <<= 1;
+        srcEnd <<= 1;
+        for (int i = srcBegin + (1 >> LO_BYTE_SHIFT); i < srcEnd; i += 2) {
+            dst[dstBegin++] = value[i];
+        }
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static boolean equals(byte[] value, byte[] other) {
+        if (value.length == other.length) {
+            int len = value.length >> 1;
+            for (int i = 0; i < len; i++) {
+                if (getChar(value, i) != getChar(other, i)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int compareTo(byte[] value, byte[] other) {
+        int len1 = length(value);
+        int len2 = length(other);
+        int lim = Math.min(len1, len2);
+        for (int k = 0; k < lim; k++) {
+            char c1 = getChar(value, k);
+            char c2 = getChar(other, k);
+            if (c1 != c2) {
+                return c1 - c2;
+            }
+        }
+        return len1 - len2;
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int compareToLatin1(byte[] value, byte[] other) {
+        int len1 = length(value);
+        int len2 = StringLatin1.length(other);
+        int lim = Math.min(len1, len2);
+        for (int k = 0; k < lim; k++) {
+            char c1 = getChar(value, k);
+            char c2 = StringLatin1.getChar(other, k);
+            if (c1 != c2) {
+                return c1 - c2;
+            }
+        }
+        return len1 - len2;
+    }
+
+    public static int hashCode(byte[] value) {
+        int h = 0;
+        int length = value.length >> 1;
+        for (int i = 0; i < length; i++) {
+            h = 31 * h + getChar(value, i);
+        }
+        return h;
+    }
+
+    public static int indexOf(byte[] value, int ch, int fromIndex) {
+        int max = value.length >> 1;
+        if (fromIndex < 0) {
+            fromIndex = 0;
+        } else if (fromIndex >= max) {
+            // Note: fromIndex might be near -1>>>1.
+            return -1;
+        }
+        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+            // handle most cases here (ch is a BMP code point or a
+            // negative value (invalid code point))
+            return indexOfChar(value, ch, fromIndex, max);
+        } else {
+            return indexOfSupplementary(value, ch, fromIndex, max);
+        }
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOf(byte[] value, byte[] str) {
+        if (str.length == 0) {
+            return 0;
+        }
+        if (value.length == 0) {
+            return -1;
+        }
+        return indexOf(value, length(value), str, length(str), 0);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
+        char first = getChar(str, 0);
+        int max = (valueCount - strCount);
+        for (int i = fromIndex; i <= max; i++) {
+            // Look for first character.
+            if (getChar(value, i) != first) {
+                while (++i <= max && getChar(value, i) != first);
+            }
+            // Found first character, now look at the rest of value
+            if (i <= max) {
+                int j = i + 1;
+                int end = j + strCount - 1;
+                for (int k = 1; j < end && getChar(value, j) == getChar(str, k); j++, k++);
+                if (j == end) {
+                    // Found whole string.
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Handles indexOf Latin1 substring in UTF16 string.
+     */
+    @HotSpotIntrinsicCandidate
+    public static int indexOfLatin1(byte[] value, byte[] str) {
+        if (str.length == 0) {
+            return 0;
+        }
+        if (value.length == 0) {
+            return -1;
+        }
+        return indexOfLatin1(value, length(value), str, str.length, 0);
+    }
+
+    @HotSpotIntrinsicCandidate
+    public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
+        char first = (char)(tgt[0] & 0xff);
+        int max = (srcCount - tgtCount);
+        for (int i = fromIndex; i <= max; i++) {
+            // Look for first character.
+            if (getChar(src, i) != first) {
+                while (++i <= max && getChar(src, i) != first);
+            }
+            // Found first character, now look at the rest of v2
+            if (i <= max) {
+                int j = i + 1;
+                int end = j + tgtCount - 1;
+                for (int k = 1;
+                     j < end && getChar(src, j) == (tgt[k] & 0xff);
+                     j++, k++);
+                if (j == end) {
+                    // Found whole string.
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    @HotSpotIntrinsicCandidate
+    private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
+        for (int i = fromIndex; i < max; i++) {
+            if (getChar(value, i) == ch) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Handles (rare) calls of indexOf with a supplementary character.
+     */
+    private static int indexOfSupplementary(byte[] value, int ch, int fromIndex, int max) {
+        if (Character.isValidCodePoint(ch)) {
+            final char hi = Character.highSurrogate(ch);
+            final char lo = Character.lowSurrogate(ch);
+            for (int i = fromIndex; i < max - 1; i++) {
+                if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    public static int lastIndexOf(byte[] src, int srcCount,
+                                  byte[] tgt, int tgtCount, int fromIndex) {
+        int min = tgtCount - 1;
+        int i = min + fromIndex;
+        int strLastIndex = tgtCount - 1;
+        char strLastChar = getChar(tgt, strLastIndex);
+
+    startSearchForLastChar:
+        while (true) {
+            while (i >= min && getChar(src, i) != strLastChar) {
+                i--;
+            }
+            if (i < min) {
+                return -1;
+            }
+            int j = i - 1;
+            int start = j - strLastIndex;
+            int k = strLastIndex - 1;
+            while (j > start) {
+                if (getChar(src, j--) != getChar(tgt, k--)) {
+                    i--;
+                    continue startSearchForLastChar;
+                }
+            }
+            return start + 1;
+        }
+    }
+
+    public static int lastIndexOf(byte[] value, int ch, int fromIndex) {
+        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+            // handle most cases here (ch is a BMP code point or a
+            // negative value (invalid code point))
+            int i = Math.min(fromIndex, (value.length >> 1) - 1);
+            for (; i >= 0; i--) {
+                if (getChar(value, i) == ch) {
+                    return i;
+                }
+            }
+            return -1;
+        } else {
+            return lastIndexOfSupplementary(value, ch, fromIndex);
+        }
+    }
+
+    /**
+     * Handles (rare) calls of lastIndexOf with a supplementary character.
+     */
+    private static int lastIndexOfSupplementary(final byte[] value, int ch, int fromIndex) {
+        if (Character.isValidCodePoint(ch)) {
+            char hi = Character.highSurrogate(ch);
+            char lo = Character.lowSurrogate(ch);
+            int i = Math.min(fromIndex, (value.length >> 1) - 2);
+            for (; i >= 0; i--) {
+                if (getChar(value, i) == hi && getChar(value, i + 1) == lo) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    public static String replace(byte[] value, char oldChar, char newChar) {
+        int len = value.length >> 1;
+        int i = -1;
+        while (++i < len) {
+            if (getChar(value, i) == oldChar) {
+                break;
+            }
+        }
+        if (i < len) {
+            byte buf[] = new byte[value.length];
+            for (int j = 0; j < i; j++) {
+                putChar(buf, j, getChar(value, j)); // TBD:arraycopy?
+            }
+            while (i < len) {
+                char c = getChar(value, i);
+                putChar(buf, i, c == oldChar ? newChar : c);
+                i++;
+           }
+           // Check if we should try to compress to latin1
+           if (String.COMPACT_STRINGS &&
+               !StringLatin1.canEncode(oldChar) &&
+               StringLatin1.canEncode(newChar)) {
+               byte[] val = compress(buf, 0, len);
+               if (val != null) {
+                   return new String(val, LATIN1);
+               }
+           }
+           return new String(buf, UTF16);
+        }
+        return null;
+    }
+
+    public static boolean regionMatchesCI(byte[] value, int toffset,
+                                          byte[] other, int ooffset, int len) {
+        int last = toffset + len;
+        while (toffset < last) {
+            char c1 = getChar(value, toffset++);
+            char c2 = getChar(other, ooffset++);
+            if (c1 == c2) {
+                continue;
+            }
+            // try converting both characters to uppercase.
+            // If the results match, then the comparison scan should
+            // continue.
+            char u1 = Character.toUpperCase(c1);
+            char u2 = Character.toUpperCase(c2);
+            if (u1 == u2) {
+                continue;
+            }
+            // Unfortunately, conversion to uppercase does not work properly
+            // for the Georgian alphabet, which has strange rules about case
+            // conversion.  So we need to make one last check before
+            // exiting.
+            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public static boolean regionMatchesCI_Latin1(byte[] value, int toffset,
+                                                 byte[] other, int ooffset,
+                                                 int len) {
+        int last = toffset + len;
+        while (toffset < last) {
+            char c1 = getChar(value, toffset++);
+            char c2 = (char)(other[ooffset++] & 0xff);
+            if (c1 == c2) {
+                continue;
+            }
+            char u1 = Character.toUpperCase(c1);
+            char u2 = Character.toUpperCase(c2);
+            if (u1 == u2) {
+                continue;
+            }
+            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
+                continue;
+            }
+            return false;
+        }
+        return true;
+    }
+
+    public static String toLowerCase(String str, byte[] value, Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException();
+        }
+        int first;
+        boolean hasSurr = false;
+        final int len = value.length >> 1;
+
+        // Now check if there are any characters that need to be changed, or are surrogate
+        for (first = 0 ; first < len; first++) {
+            int cp = (int)getChar(value, first);
+            if (Character.isSurrogate((char)cp)) {
+                hasSurr = true;
+                break;
+            }
+            if (cp != Character.toLowerCase(cp)) {  // no need to check Character.ERROR
+                break;
+            }
+        }
+        if (first == len)
+            return str;
+        byte[] result = new byte[value.length];
+        System.arraycopy(value, 0, result, 0, first << 1);  // Just copy the first few
+                                                            // lowerCase characters.
+        String lang = locale.getLanguage();
+        if (lang == "tr" || lang == "az" || lang == "lt") {
+            return toLowerCaseEx(str, value, result, first, locale, true);
+        }
+        if (hasSurr) {
+            return toLowerCaseEx(str, value, result, first, locale, false);
+        }
+        int bits = 0;
+        for (int i = first; i < len; i++) {
+            int cp = (int)getChar(value, i);
+            if (cp == '\u03A3' ||                       // GREEK CAPITAL LETTER SIGMA
+                Character.isSurrogate((char)cp)) {
+                return toLowerCaseEx(str, value, result, i, locale, false);
+            }
+            if (cp == '\u0130') {                       // LATIN CAPITAL LETTER I WITH DOT ABOVE
+                return toLowerCaseEx(str, value, result, i, locale, true);
+            }
+            cp = Character.toLowerCase(cp);
+            if (!Character.isBmpCodePoint(cp)) {
+                return toLowerCaseEx(str, value, result, i, locale, false);
+            }
+            bits |= cp;
+            putChar(result, i, cp);
+        }
+        if (bits >>> 8 != 0) {
+            return new String(result, UTF16);
+        } else {
+            return newString(result, 0, len);
+        }
+    }
+
+    private static String toLowerCaseEx(String str, byte[] value,
+                                        byte[] result, int first, Locale locale,
+                                        boolean localeDependent) {
+        int resultOffset = first;
+        int length = value.length >> 1;
+        int srcCount;
+        for (int i = first; i < length; i += srcCount) {
+            int srcChar = getChar(value, i);
+            int lowerChar;
+            char[] lowerCharArray;
+            srcCount = 1;
+            if (Character.isSurrogate((char)srcChar)) {
+                srcChar = codePointAt(value, i, length);
+                srcCount = Character.charCount(srcChar);
+            }
+            if (localeDependent ||
+                srcChar == '\u03A3' ||  // GREEK CAPITAL LETTER SIGMA
+                srcChar == '\u0130') {  // LATIN CAPITAL LETTER I WITH DOT ABOVE
+                lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
+            } else {
+                lowerChar = Character.toLowerCase(srcChar);
+            }
+            if (Character.isBmpCodePoint(lowerChar)) {    // Character.ERROR is not a bmp
+                putChar(result, resultOffset++, lowerChar);
+            } else {
+                if (lowerChar == Character.ERROR) {
+                    lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
+                } else {
+                    lowerCharArray = Character.toChars(lowerChar);
+                }
+                /* Grow result if needed */
+                int mapLen = lowerCharArray.length;
+                if (mapLen > srcCount) {
+                    byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
+                    System.arraycopy(result, 0, result2, 0, resultOffset << 1);
+                    result = result2;
+                }
+                for (int x = 0; x < mapLen; ++x) {
+                    putChar(result, resultOffset++, lowerCharArray[x]);
+                }
+            }
+        }
+        return newString(result, 0, resultOffset);
+    }
+
+    public static String toUpperCase(String str, byte[] value, Locale locale) {
+        if (locale == null) {
+            throw new NullPointerException();
+        }
+        int first;
+        boolean hasSurr = false;
+        final int len = value.length >> 1;
+
+        // Now check if there are any characters that need to be changed, or are surrogate
+        for (first = 0 ; first < len; first++) {
+            int cp = (int)getChar(value, first);
+            if (Character.isSurrogate((char)cp)) {
+                hasSurr = true;
+                break;
+            }
+            if (cp != Character.toUpperCaseEx(cp)) {   // no need to check Character.ERROR
+                break;
+            }
+        }
+        if (first == len) {
+            return str;
+        }
+        byte[] result = new byte[value.length];
+        System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few
+                                                           // upperCase characters.
+        String lang = locale.getLanguage();
+        if (lang == "tr" || lang == "az" || lang == "lt") {
+            return toUpperCaseEx(str, value, result, first, locale, true);
+        }
+        if (hasSurr) {
+            return toUpperCaseEx(str, value, result, first, locale, false);
+        }
+        int bits = 0;
+        for (int i = first; i < len; i++) {
+            int cp = (int)getChar(value, i);
+            if (Character.isSurrogate((char)cp)) {
+                return toUpperCaseEx(str, value, result, i, locale, false);
+            }
+            cp = Character.toUpperCaseEx(cp);
+            if (!Character.isBmpCodePoint(cp)) {    // Character.ERROR is not bmp
+                return toUpperCaseEx(str, value, result, i, locale, false);
+            }
+            bits |= cp;
+            putChar(result, i, cp);
+        }
+        if (bits >>> 8 != 0) {
+            return new String(result, UTF16);
+        } else {
+            return newString(result, 0, len);
+        }
+    }
+
+    private static String toUpperCaseEx(String str, byte[] value,
+                                        byte[] result, int first,
+                                        Locale locale, boolean localeDependent)
+    {
+        int resultOffset = first;
+        int length = value.length >> 1;
+        int srcCount;
+        for (int i = first; i < length; i += srcCount) {
+            int srcChar = getChar(value, i);
+            int upperChar;
+            char[] upperCharArray;
+            srcCount = 1;
+            if (Character.isSurrogate((char)srcChar)) {
+                srcChar = codePointAt(value, i, length);
+                srcCount = Character.charCount(srcChar);
+            }
+            if (localeDependent) {
+                upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
+            } else {
+                upperChar = Character.toUpperCaseEx(srcChar);
+            }
+            if (Character.isBmpCodePoint(upperChar)) {
+                putChar(result, resultOffset++, upperChar);
+            } else {
+                if (upperChar == Character.ERROR) {
+                    if (localeDependent) {
+                        upperCharArray =
+                            ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
+                    } else {
+                        upperCharArray = Character.toUpperCaseCharArray(srcChar);
+                    }
+                } else {
+                    upperCharArray = Character.toChars(upperChar);
+                }
+                /* Grow result if needed */
+                int mapLen = upperCharArray.length;
+                if (mapLen > srcCount) {
+                    byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
+                    System.arraycopy(result, 0, result2, 0, resultOffset << 1);
+                    result = result2;
+                 }
+                 for (int x = 0; x < mapLen; ++x) {
+                    putChar(result, resultOffset++, upperCharArray[x]);
+                 }
+            }
+        }
+        return newString(result, 0, resultOffset);
+    }
+
+    public static String trim(byte[] value) {
+        int length = value.length >> 1;
+        int len = length;
+        int st = 0;
+        while (st < len && getChar(value, st) <= ' ') {
+            st++;
+        }
+        while (st < len && getChar(value, len - 1) <= ' ') {
+            len--;
+        }
+        return ((st > 0) || (len < length )) ?
+            new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) :
+            null;
+    }
+
+    public static void putChars(byte[] val, int index, char[] str, int off, int end) {
+        while (off < end) {
+            putChar(val, index++, str[off++]);
+        }
+    }
+
+    public static String newString(byte[] val, int index, int len) {
+        if (String.COMPACT_STRINGS) {
+            byte[] buf = compress(val, index, len);
+            if (buf != null) {
+                return new String(buf, LATIN1);
+            }
+        }
+        int last = index + len;
+        return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
+    }
+
+    public static void fillNull(byte[] val, int index, int end) {
+        Arrays.fill(val, index << 1, end << 1, (byte)0);
+    }
+
+    static class CharsSpliterator implements Spliterator.OfInt {
+        private final byte[] array;
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        CharsSpliterator(byte[] array, int acs) {
+            this(array, 0, array.length >> 1, acs);
+        }
+
+        CharsSpliterator(byte[] array, int origin, int fence, int acs) {
+            this.array = array;
+            this.index = origin;
+            this.fence = fence;
+            this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
+                      | Spliterator.SUBSIZED;
+        }
+
+        @Override
+        public OfInt trySplit() {
+            int lo = index, mid = (lo + fence) >>> 1;
+            return (lo >= mid)
+                   ? null
+                   : new CharsSpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            byte[] a; int i, hi; // hoist accesses and checks from loop
+            if (action == null)
+                throw new NullPointerException();
+            if (((a = array).length >> 1) >= (hi = fence) &&
+                (i = index) >= 0 && i < (index = hi)) {
+                do { action.accept(getChar(a, i)); } while (++i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (index >= 0 && index < fence) {
+                action.accept(getChar(array, index++));
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    static class CodePointsSpliterator implements Spliterator.OfInt {
+        private final byte[] array;
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        CodePointsSpliterator(byte[] array, int acs) {
+            this(array, 0, array.length >> 1, acs);
+        }
+
+        CodePointsSpliterator(byte[] array, int origin, int fence, int acs) {
+            this.array = array;
+            this.index = origin;
+            this.fence = fence;
+            this.cs = acs | Spliterator.ORDERED;
+        }
+
+        @Override
+        public OfInt trySplit() {
+            int lo = index, mid = (lo + fence) >>> 1;
+            if (lo >= mid)
+                return null;
+
+            int midOneLess;
+            // If the mid-point intersects a surrogate pair
+            if (Character.isLowSurrogate(getChar(array, mid)) &&
+                Character.isHighSurrogate(getChar(array, midOneLess = (mid -1)))) {
+                // If there is only one pair it cannot be split
+                if (lo >= midOneLess)
+                    return null;
+                // Shift the mid-point to align with the surrogate pair
+                return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
+            }
+            return new CodePointsSpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            byte[] a; int i, hi; // hoist accesses and checks from loop
+            if (action == null)
+                throw new NullPointerException();
+            if (((a = array).length >> 1) >= (hi = fence) &&
+                (i = index) >= 0 && i < (index = hi)) {
+                do {
+                    i = advance(a, i, hi, action);
+                } while (i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (index >= 0 && index < fence) {
+                index = advance(array, index, fence, action);
+                return true;
+            }
+            return false;
+        }
+
+        // Advance one code point from the index, i, and return the next
+        // index to advance from
+        private static int advance(byte[] a, int i, int hi, IntConsumer action) {
+            char c1 = getChar(a, i++);
+            int cp = c1;
+            if (Character.isHighSurrogate(c1) && i < hi) {
+                char c2 = getChar(a, i);
+                if (Character.isLowSurrogate(c2)) {
+                    i++;
+                    cp = Character.toCodePoint(c1, c2);
+                }
+            }
+            action.accept(cp);
+            return i;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////
+
+    public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
+        checkOffset(srcEnd, val.length >> 1);
+        getChars(val, srcBegin, srcEnd, dst, dstBegin);
+    }
+
+    public static void putCharSB(byte[] val, int index, int c) {
+        checkIndex(index, val.length >> 1);
+        putChar(val, index, c);
+    }
+
+    public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) {
+        checkOffset(index + end - off, val.length >> 1);
+        putChars(val, index, ca, off, end);
+    }
+
+    public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) {
+        checkOffset(index + end - off, val.length >> 1);
+        for (int i = off; i < end; i++) {
+            putChar(val, index++, s.charAt(i));
+        }
+    }
+
+    public static int codePointAtSB(byte[] val, int index, int end) {
+        checkOffset(end, val.length >> 1);
+        return codePointAt(val, index, end);
+    }
+
+    public static int codePointBeforeSB(byte[] val, int index) {
+        checkOffset(index, val.length >> 1);
+        return codePointBefore(val, index);
+    }
+
+    public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) {
+        checkOffset(endIndex, val.length >> 1);
+        return codePointCount(val, beginIndex, endIndex);
+    }
+
+    public static String newStringSB(byte[] val, int index, int len) {
+        checkOffset(index + len, val.length >> 1);
+        return newString(val, index, len);
+    }
+
+    ////////////////////////////////////////////////////////////////
+
+    private static native boolean isBigEndian();
+
+    static final int HI_BYTE_SHIFT;
+    static final int LO_BYTE_SHIFT;
+    static {
+        if (isBigEndian()) {
+            HI_BYTE_SHIFT = 8;
+            LO_BYTE_SHIFT = 0;
+        } else {
+            HI_BYTE_SHIFT = 0;
+            LO_BYTE_SHIFT = 8;
+        }
+    }
+
+    static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
+}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java	Wed Jul 05 21:00:20 2017 +0200
@@ -34,14 +34,16 @@
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Field;
 import java.util.Arrays;
-import java.util.HashMap;
+import java.util.function.Function;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
 
+import jdk.internal.org.objectweb.asm.FieldVisitor;
 import sun.invoke.util.ValueConversions;
 import sun.invoke.util.Wrapper;
 
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Type;
 
 /**
  * The flavor of method handle which emulates an invoke instruction
@@ -217,7 +219,7 @@
         /*non-public*/ int fieldCount() {
             return 1;
         }
-        /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
+        /*non-public*/ static final SpeciesData SPECIES_DATA = new SpeciesData("L", Species_L.class);
         /*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) {
             return new Species_L(mt, lf, argL0);
         }
@@ -335,7 +337,7 @@
 
         static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
 
-        private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
+        SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
             this.typeChars = types;
             this.typeCodes = basicTypes(types);
             this.clazz = clazz;
@@ -355,26 +357,14 @@
             assert(!INIT_DONE);
             if (constructor() == null) {
                 String types = typeChars;
+                CACHE.put(types, this);
                 Factory.makeCtors(clazz, types, this.constructor);
                 Factory.makeGetters(clazz, types, this.getters);
                 Factory.makeNominalGetters(types, this.nominalGetters, this.getters);
             }
         }
 
-        private SpeciesData(String typeChars) {
-            // Placeholder only.
-            this.typeChars = typeChars;
-            this.typeCodes = basicTypes(typeChars);
-            this.clazz = null;
-            this.constructor = null;
-            this.getters = null;
-            this.nominalGetters = null;
-            this.extensions = null;
-        }
-        private boolean isPlaceholder() { return clazz == null; }
-
-        private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
-        static { CACHE.put("", EMPTY); }  // make bootstrap predictable
+        private static final ConcurrentMap<String, SpeciesData> CACHE = new ConcurrentHashMap<>();
         private static final boolean INIT_DONE;  // set after <clinit> finishes...
 
         SpeciesData extendWith(byte type) {
@@ -390,62 +380,52 @@
         }
 
         private static SpeciesData get(String types) {
-            // Acquire cache lock for query.
-            SpeciesData d = lookupCache(types);
-            if (!d.isPlaceholder())
-                return d;
-            synchronized (d) {
-                // Use synch. on the placeholder to prevent multiple instantiation of one species.
-                // Creating this class forces a recursive call to getForClass.
-                if (lookupCache(types).isPlaceholder())
-                    Factory.generateConcreteBMHClass(types);
-            }
-            // Reacquire cache lock.
-            d = lookupCache(types);
-            // Class loading must have upgraded the cache.
-            assert(d != null && !d.isPlaceholder());
-            return d;
-        }
-        static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
-            // clazz is a new class which is initializing its SPECIES_DATA field
-            return updateCache(types, new SpeciesData(types, clazz));
-        }
-        private static synchronized SpeciesData lookupCache(String types) {
-            SpeciesData d = CACHE.get(types);
-            if (d != null)  return d;
-            d = new SpeciesData(types);
-            assert(d.isPlaceholder());
-            CACHE.put(types, d);
-            return d;
-        }
-        private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
-            SpeciesData d2;
-            assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
-            assert(!d.isPlaceholder());
-            CACHE.put(types, d);
-            return d;
+            return CACHE.computeIfAbsent(types, new Function<String, SpeciesData>() {
+                @Override
+                public SpeciesData apply(String types) {
+                    Class<? extends BoundMethodHandle> bmhcl = Factory.getConcreteBMHClass(types);
+                    // SpeciesData instantiation may throw VirtualMachineError because of
+                    // code cache overflow...
+                    SpeciesData speciesData = new SpeciesData(types, bmhcl);
+                    // CHM.computeIfAbsent ensures only one SpeciesData will be set
+                    // successfully on the concrete BMH class if ever
+                    Factory.setSpeciesDataToConcreteBMHClass(bmhcl, speciesData);
+                    // the concrete BMH class is published via SpeciesData instance
+                    // returned here only after it's SPECIES_DATA field is set
+                    return speciesData;
+                }
+            });
         }
 
-        static {
-            // pre-fill the BMH speciesdata cache with BMH's inner classes
-            final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
+        /**
+         * This is to be called when assertions are enabled. It checks whether SpeciesData for all of the statically
+         * defined species subclasses of BoundMethodHandle has been added to the SpeciesData cache. See below in the
+         * static initializer for
+         */
+        static boolean speciesDataCachePopulated() {
+            Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
             try {
                 for (Class<?> c : rootCls.getDeclaredClasses()) {
                     if (rootCls.isAssignableFrom(c)) {
                         final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
-                        SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
+                        SpeciesData d = Factory.getSpeciesDataFromConcreteBMHClass(cbmh);
                         assert(d != null) : cbmh.getName();
                         assert(d.clazz == cbmh);
-                        assert(d == lookupCache(d.typeChars));
+                        assert(CACHE.get(d.typeChars) == d);
                     }
                 }
             } catch (Throwable e) {
                 throw newInternalError(e);
             }
+            return true;
+        }
 
-            for (SpeciesData d : CACHE.values()) {
-                d.initForBootstrap();
-            }
+        static {
+            // Pre-fill the BMH species-data cache with EMPTY and all BMH's inner subclasses.
+            EMPTY.initForBootstrap();
+            Species_L.SPECIES_DATA.initForBootstrap();
+            // check that all static SpeciesData instances have been initialized
+            assert speciesDataCachePopulated();
             // Note:  Do not simplify this, because INIT_DONE must not be
             // a compile-time constant during bootstrapping.
             INIT_DONE = Boolean.TRUE;
@@ -479,6 +459,7 @@
         static final String BMH_SIG  = "L"+BMH+";";
         static final String SPECIES_DATA     = "java/lang/invoke/BoundMethodHandle$SpeciesData";
         static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";";
+        static final String STABLE_SIG       = "Ljava/lang/invoke/Stable;";
 
         static final String SPECIES_PREFIX_NAME = "Species_";
         static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME;
@@ -493,6 +474,26 @@
 
         static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
 
+        static final ConcurrentMap<String, Class<? extends BoundMethodHandle>> CLASS_CACHE = new ConcurrentHashMap<>();
+
+        /**
+         * Get a concrete subclass of BMH for a given combination of bound types.
+         *
+         * @param types the type signature, wherein reference types are erased to 'L'
+         * @return the concrete BMH class
+         */
+        static Class<? extends BoundMethodHandle> getConcreteBMHClass(String types) {
+            // CHM.computeIfAbsent ensures generateConcreteBMHClass is called
+            // only once per key.
+            return CLASS_CACHE.computeIfAbsent(
+                types, new Function<String, Class<? extends BoundMethodHandle>>() {
+                    @Override
+                    public Class<? extends BoundMethodHandle> apply(String types) {
+                        return generateConcreteBMHClass(types);
+                    }
+                });
+        }
+
         /**
          * Generate a concrete subclass of BMH for a given combination of bound types.
          *
@@ -529,7 +530,7 @@
          *     }
          *     final SpeciesData speciesData() { return SPECIES_DATA; }
          *     final int fieldCount() { return 3; }
-         *     static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
+         *     &#64;Stable static SpeciesData SPECIES_DATA; // injected afterwards
          *     static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
          *         return new Species_LLI(mt, lf, argL0, argL1, argI2);
          *     }
@@ -568,7 +569,9 @@
             cw.visitSource(sourceFile, null);
 
             // emit static types and SPECIES_DATA fields
-            cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
+            FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null);
+            fw.visitAnnotation(STABLE_SIG, true);
+            fw.visitEnd();
 
             // emit bound argument fields
             for (int i = 0; i < types.length(); ++i) {
@@ -694,17 +697,6 @@
                 mv.visitEnd();
             }
 
-            // emit class initializer
-            mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
-            mv.visitCode();
-            mv.visitLdcInsn(types);
-            mv.visitLdcInsn(Type.getObjectType(className));
-            mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG, false);
-            mv.visitFieldInsn(PUTSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
-            mv.visitInsn(RETURN);
-            mv.visitMaxs(0, 0);
-            mv.visitEnd();
-
             cw.visitEnd();
 
             // load class
@@ -715,7 +707,6 @@
                 UNSAFE.defineClass(className, classFile, 0, classFile.length,
                                    BoundMethodHandle.class.getClassLoader(), null)
                     .asSubclass(BoundMethodHandle.class);
-            UNSAFE.ensureClassInitialized(bmhClass);
 
             return bmhClass;
         }
@@ -785,7 +776,7 @@
         // Auxiliary methods.
         //
 
-        static SpeciesData speciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
+        static SpeciesData getSpeciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
             try {
                 Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
                 return (SpeciesData) F_SPECIES_DATA.get(null);
@@ -794,6 +785,16 @@
             }
         }
 
+        static void setSpeciesDataToConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh, SpeciesData speciesData) {
+            try {
+                Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
+                assert F_SPECIES_DATA.getDeclaredAnnotation(Stable.class) != null;
+                F_SPECIES_DATA.set(null, speciesData);
+            } catch (ReflectiveOperationException ex) {
+                throw newInternalError(ex);
+            }
+        }
+
         /**
          * Field names in concrete BMHs adhere to this pattern:
          * arg + type + index
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,7 +25,7 @@
 
 package java.lang.invoke;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import java.lang.reflect.Method;
 import java.util.Arrays;
 import sun.invoke.util.VerifyAccess;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 import jdk.internal.org.objectweb.asm.*;
 import sun.invoke.util.BytecodeDescriptor;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.security.action.GetPropertyAction;
 
 import java.io.FilePermission;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java	Wed Jul 05 21:00:20 2017 +0200
@@ -775,7 +775,7 @@
         // Sample classes from each package we are willing to bind to statically:
         java.lang.Object.class,
         java.util.Arrays.class,
-        sun.misc.Unsafe.class
+        jdk.internal.misc.Unsafe.class
         //MethodHandle.class already covered
     };
 
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Wed Jul 05 21:00:20 2017 +0200
@@ -694,8 +694,11 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(clazz, getReferenceKind(), name, getType());
+        // Avoid autoboxing getReferenceKind(), since this is used early and will force
+        // early initialization of Byte$ByteCache
+        return Objects.hash(clazz, new Byte(getReferenceKind()), name, getType());
     }
+
     @Override
     public boolean equals(Object that) {
         return (that instanceof MemberName && this.equals((MemberName)that));
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Wed Jul 05 21:00:20 2017 +0200
@@ -50,7 +50,7 @@
     static native int getMembers(Class<?> defc, String matchName, String matchSig,
             int matchFlags, Class<?> caller, int skip, MemberName[] results);
 
-    /// Field layout queries parallel to sun.misc.Unsafe:
+    /// Field layout queries parallel to jdk.internal.misc.Unsafe:
     static native long objectFieldOffset(MemberName self);  // e.g., returns vmindex
     static native long staticFieldOffset(MemberName self);  // e.g., returns vmindex
     static native Object staticFieldBase(MemberName self);  // e.g., returns clazz
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * This class consists exclusively of static names internal to the
--- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java	Wed Jul 05 21:00:20 2017 +0200
@@ -3726,12 +3726,12 @@
     }
 
     private static class UnsafeHolder {
-        private static final sun.misc.Unsafe unsafe;
+        private static final jdk.internal.misc.Unsafe unsafe;
         private static final long intCompactOffset;
         private static final long intValOffset;
         static {
             try {
-                unsafe = sun.misc.Unsafe.getUnsafe();
+                unsafe = jdk.internal.misc.Unsafe.getUnsafe();
                 intCompactOffset = unsafe.objectFieldOffset
                     (BigDecimal.class.getDeclaredField("intCompact"));
                 intValOffset = unsafe.objectFieldOffset
--- a/jdk/src/java.base/share/classes/java/math/BigInteger.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java	Wed Jul 05 21:00:20 2017 +0200
@@ -4526,12 +4526,12 @@
 
     // Support for resetting final fields while deserializing
     private static class UnsafeHolder {
-        private static final sun.misc.Unsafe unsafe;
+        private static final jdk.internal.misc.Unsafe unsafe;
         private static final long signumOffset;
         private static final long magOffset;
         static {
             try {
-                unsafe = sun.misc.Unsafe.getUnsafe();
+                unsafe = jdk.internal.misc.Unsafe.getUnsafe();
                 signumOffset = unsafe.objectFieldOffset
                     (BigInteger.class.getDeclaredField("signum"));
                 magOffset = unsafe.objectFieldOffset
--- a/jdk/src/java.base/share/classes/java/net/Inet6Address.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/net/Inet6Address.java	Wed Jul 05 21:00:20 2017 +0200
@@ -576,11 +576,11 @@
     };
 
     private static final long FIELDS_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
 
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             FIELDS_OFFSET = unsafe.objectFieldOffset(
                     Inet6Address.class.getDeclaredField("holder6"));
             UNSAFE = unsafe;
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,6 +29,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.ServiceLoader;
 import java.security.AccessController;
 import java.io.ObjectStreamException;
@@ -733,7 +734,7 @@
      */
     public String toString() {
         String hostName = holder().getHostName();
-        return ((hostName != null) ? hostName : "")
+        return Objects.toString(hostName, "")
             + "/" + getHostAddress();
     }
 
@@ -1493,11 +1494,11 @@
     }
 
     private static final long FIELDS_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
 
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             FIELDS_OFFSET = unsafe.objectFieldOffset(
                 InetAddress.class.getDeclaredField("holder")
             );
--- a/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/net/InetSocketAddress.java	Wed Jul 05 21:00:20 2017 +0200
@@ -303,10 +303,10 @@
     }
 
     private static final long FIELDS_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             FIELDS_OFFSET = unsafe.objectFieldOffset(
                     InetSocketAddress.class.getDeclaredField("holder"));
             UNSAFE = unsafe;
--- a/jdk/src/java.base/share/classes/java/net/SocketOptions.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/net/SocketOptions.java	Wed Jul 05 21:00:20 2017 +0200
@@ -61,21 +61,21 @@
      * If the requested option is binary, it can be set using this method by
      * a java.lang.Boolean:
      * <BR><PRE>
-     * s.setOption(TCP_NODELAY, new Boolean(true));
+     * s.setOption(TCP_NODELAY, Boolean.TRUE);
      *    // OK - enables TCP_NODELAY, a binary option
      * </PRE>
      * <BR>
-     * Any option can be disabled using this method with a Boolean(false):
+     * Any option can be disabled using this method with a Boolean.FALSE:
      * <BR><PRE>
-     * s.setOption(TCP_NODELAY, new Boolean(false));
+     * s.setOption(TCP_NODELAY, Boolean.FALSE);
      *    // OK - disables TCP_NODELAY
-     * s.setOption(SO_LINGER, new Boolean(false));
+     * s.setOption(SO_LINGER, Boolean.FALSE);
      *    // OK - disables SO_LINGER
      * </PRE>
      * <BR>
      * For an option that has a notion of on and off, and requires
      * a non-boolean parameter, setting its value to anything other than
-     * <I>Boolean(false)</I> implicitly enables it.
+     * <I>Boolean.FALSE</I> implicitly enables it.
      * <BR>
      * Throws SocketException if the option is unrecognized,
      * the socket is closed, or some low-level error occurred
@@ -91,8 +91,8 @@
 
     /**
      * Fetch the value of an option.
-     * Binary options will return java.lang.Boolean(true)
-     * if enabled, java.lang.Boolean(false) if disabled, e.g.:
+     * Binary options will return java.lang.Boolean.TRUE
+     * if enabled, java.lang.Boolean.FALSE if disabled, e.g.:
      * <BR><PRE>
      * SocketImpl s;
      * ...
@@ -105,13 +105,13 @@
      * <P>
      * For options that take a particular type as a parameter,
      * getOption(int) will return the parameter's value, else
-     * it will return java.lang.Boolean(false):
+     * it will return java.lang.Boolean.FALSE:
      * <PRE>
      * Object o = s.getOption(SO_LINGER);
      * if (o instanceof Integer) {
      *     System.out.print("Linger time is " + ((Integer)o).intValue());
      * } else {
-     *   // the true type of o is java.lang.Boolean(false);
+     *   // the true type of o is java.lang.Boolean.FALSE;
      * }
      * </PRE>
      *
--- a/jdk/src/java.base/share/classes/java/net/URLConnection.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java	Wed Jul 05 21:00:20 2017 +0200
@@ -32,6 +32,7 @@
 import java.util.Hashtable;
 import java.util.Date;
 import java.util.Iterator;
+import java.util.Objects;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
 import java.util.StringTokenizer;
@@ -1250,7 +1251,7 @@
 
         if (handler != null) {
             ContentHandler h = handlers.putIfAbsent(contentType, handler);
-            return h != null ? h : handler;
+            return Objects.requireNonNullElse(h, handler);
         }
 
         try {
@@ -1263,7 +1264,7 @@
         assert handler != null;
 
         ContentHandler h = handlers.putIfAbsent(contentType, handler);
-        return h != null ? h : handler;
+        return Objects.requireNonNullElse(h, handler);
     }
 
     /*
--- a/jdk/src/java.base/share/classes/java/nio/Bits.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/nio/Bits.java	Wed Jul 05 21:00:20 2017 +0200
@@ -32,7 +32,7 @@
 import jdk.internal.misc.JavaNioAccess;
 import jdk.internal.misc.JavaLangRefAccess;
 import jdk.internal.misc.SharedSecrets;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.misc.VM;
 
 /**
--- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Wed Jul 05 21:00:20 2017 +0200
@@ -29,7 +29,7 @@
 
 import java.io.FileDescriptor;
 import sun.misc.Cleaner;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.misc.VM;
 import sun.nio.ch.DirectBuffer;
 
--- a/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 package java.nio;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
 #if[rw]
@@ -477,7 +477,7 @@
 #if[rw]
 
     public float getFloat() {
-        int x = unsafe.getIntUnaligned(hb, byteOffset(nextPutIndex(4)), bigEndian);
+        int x = unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
         return Float.intBitsToFloat(x);
     }
 
--- a/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/nio/MappedByteBuffer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,7 +26,7 @@
 package java.nio;
 
 import java.io.FileDescriptor;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 
 /**
--- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java	Wed Jul 05 21:00:20 2017 +0200
@@ -37,6 +37,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 import java.util.ServiceLoader;
 import java.util.ServiceConfigurationError;
@@ -625,6 +626,7 @@
 
     private final String name;          // tickles a bug in oldjavac
     private final String[] aliases;     // tickles a bug in oldjavac
+    private final String[] zeroAliases = new String[0];
     private Set<String> aliasSet = null;
 
     /**
@@ -642,7 +644,7 @@
      */
     protected Charset(String canonicalName, String[] aliases) {
         checkName(canonicalName);
-        String[] as = (aliases == null) ? new String[0] : aliases;
+        String[] as = Objects.requireNonNullElse(aliases, zeroAliases);
         for (int i = 0; i < as.length; i++)
             checkName(as[i]);
         this.name = canonicalName;
--- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java	Wed Jul 05 21:00:20 2017 +0200
@@ -419,7 +419,7 @@
      * @since 1.5
      */
     public String getAlgorithm() {
-        return (algorithm != null) ? algorithm : "unknown";
+        return Objects.toString(algorithm, "unknown");
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/time/ZoneId.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/time/ZoneId.java	Wed Jul 05 21:00:20 2017 +0200
@@ -310,8 +310,7 @@
     public static ZoneId of(String zoneId, Map<String, String> aliasMap) {
         Objects.requireNonNull(zoneId, "zoneId");
         Objects.requireNonNull(aliasMap, "aliasMap");
-        String id = aliasMap.get(zoneId);
-        id = (id != null ? id : zoneId);
+        String id = Objects.requireNonNullElse(aliasMap.get(zoneId), zoneId);
         return of(id);
     }
 
--- a/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java	Wed Jul 05 21:00:20 2017 +0200
@@ -177,7 +177,7 @@
     static Chronology from(TemporalAccessor temporal) {
         Objects.requireNonNull(temporal, "temporal");
         Chronology obj = temporal.query(TemporalQueries.chronology());
-        return (obj != null ? obj : IsoChronology.INSTANCE);
+        return Objects.requireNonNullElse(obj, IsoChronology.INSTANCE);
     }
 
     //-----------------------------------------------------------------------
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java	Wed Jul 05 21:00:20 2017 +0200
@@ -2892,7 +2892,8 @@
 
         @Override
         public String toString() {
-            return "ReducedValue(" + field + "," + minWidth + "," + maxWidth + "," + (baseDate != null ? baseDate : baseValue) + ")";
+            return "ReducedValue(" + field + "," + minWidth + "," + maxWidth +
+                    "," + Objects.requireNonNullElse(baseDate, baseValue) + ")";
         }
     }
 
@@ -3851,6 +3852,10 @@
                     return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
                 } else if (context.charEquals(nextChar, 'G') && length >= position + 3 &&
                         context.charEquals(nextNextChar, 'M') && context.charEquals(text.charAt(position + 2), 'T')) {
+                    if (length >= position + 4 && context.charEquals(text.charAt(position + 3), '0')) {
+                        context.setParsed(ZoneId.of("GMT0"));
+                        return position + 4;
+                    }
                     return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
                 }
             }
@@ -4328,7 +4333,7 @@
         private String getChronologyName(Chronology chrono, Locale locale) {
             String key = "calendarname." + chrono.getCalendarType();
             String name = DateTimeTextProvider.getLocalizedResource(key, locale);
-            return name != null ? name : chrono.getId();
+            return Objects.requireNonNullElseGet(name, () -> chrono.getId());
         }
     }
 
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimePrintContext.java	Wed Jul 05 21:00:20 2017 +0200
@@ -146,7 +146,7 @@
         if (overrideZone != null) {
             // if have zone and instant, calculation is simple, defaulting chrono if necessary
             if (temporal.isSupported(INSTANT_SECONDS)) {
-                Chronology chrono = (effectiveChrono != null ? effectiveChrono : IsoChronology.INSTANCE);
+                Chronology chrono = Objects.requireNonNullElse(effectiveChrono, IsoChronology.INSTANCE);
                 return chrono.zonedDateTime(Instant.from(temporal), overrideZone);
             }
             // block changing zone on OffsetTime, and similar problem cases
--- a/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/time/temporal/IsoFields.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -102,7 +102,7 @@
  * The complete date is expressed using three fields:
  * <ul>
  * <li>{@link #DAY_OF_QUARTER DAY_OF_QUARTER} - the day within the quarter, from 1 to 90, 91 or 92
- * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the week within the week-based-year
+ * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the quarter within the year, from 1 to 4
  * <li>{@link ChronoField#YEAR YEAR} - the standard ISO year
  * </ul>
  *
@@ -571,9 +571,6 @@
         //-------------------------------------------------------------------------
         private static final int[] QUARTER_DAYS = {0, 90, 181, 273, 0, 91, 182, 274};
 
-        private static boolean isIso(TemporalAccessor temporal) {
-            return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
-        }
 
         private static void ensureIso(TemporalAccessor temporal) {
             if (isIso(temporal) == false) {
@@ -681,7 +678,7 @@
 
         @Override
         public boolean isSupportedBy(Temporal temporal) {
-            return temporal.isSupported(EPOCH_DAY);
+            return temporal.isSupported(EPOCH_DAY) && isIso(temporal);
         }
 
         @SuppressWarnings("unchecked")
@@ -721,4 +718,8 @@
             return name;
         }
     }
+
+    static boolean isIso(TemporalAccessor temporal) {
+        return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
+    }
 }
--- a/jdk/src/java.base/share/classes/java/util/Arrays.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Arrays.java	Wed Jul 05 21:00:20 2017 +0200
@@ -2882,6 +2882,7 @@
      * @param a2 the other array to be tested for equality
      * @return {@code true} if the two arrays are equal
      */
+    @HotSpotIntrinsicCandidate
     public static boolean equals(byte[] a, byte[] a2) {
         if (a==a2)
             return true;
--- a/jdk/src/java.base/share/classes/java/util/Collections.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Collections.java	Wed Jul 05 21:00:20 2017 +0200
@@ -2090,7 +2090,8 @@
      * through the returned set.<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * set when iterating over it:
+     * collection when traversing it via {@link Iterator}, {@link Spliterator}
+     * or {@link Stream}:
      * <pre>
      *  Set s = Collections.synchronizedSet(new HashSet());
      *      ...
@@ -2149,8 +2150,9 @@
      * through the returned sorted set (or its views).<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * sorted set when iterating over it or any of its {@code subSet},
-     * {@code headSet}, or {@code tailSet} views.
+     * sorted set when traversing it or any of its {@code subSet},
+     * {@code headSet}, or {@code tailSet} views via {@link Iterator},
+     * {@link Spliterator} or {@link Stream}:
      * <pre>
      *  SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
      *      ...
@@ -2240,8 +2242,9 @@
      * accomplished through the returned navigable set (or its views).<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * navigable set when iterating over it or any of its {@code subSet},
-     * {@code headSet}, or {@code tailSet} views.
+     * navigable set when traversing it, or any of its {@code subSet},
+     * {@code headSet}, or {@code tailSet} views, via {@link Iterator},
+     * {@link Spliterator} or {@link Stream}:
      * <pre>
      *  NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
      *      ...
@@ -2355,7 +2358,8 @@
      * through the returned list.<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * list when iterating over it:
+     * list when traversing it via {@link Iterator}, {@link Spliterator}
+     * or {@link Stream}:
      * <pre>
      *  List list = Collections.synchronizedList(new ArrayList());
      *      ...
@@ -2523,7 +2527,8 @@
      * through the returned map.<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * map when iterating over any of its collection views:
+     * map when traversing any of its collection views via {@link Iterator},
+     * {@link Spliterator} or {@link Stream}:
      * <pre>
      *  Map m = Collections.synchronizedMap(new HashMap());
      *      ...
@@ -2700,9 +2705,10 @@
      * through the returned sorted map (or its views).<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * sorted map when iterating over any of its collection views, or the
+     * sorted map when traversing any of its collection views, or the
      * collections views of any of its {@code subMap}, {@code headMap} or
-     * {@code tailMap} views.
+     * {@code tailMap} views, via {@link Iterator}, {@link Spliterator} or
+     * {@link Stream}:
      * <pre>
      *  SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
      *      ...
@@ -2797,9 +2803,10 @@
      * accomplished through the returned navigable map (or its views).<p>
      *
      * It is imperative that the user manually synchronize on the returned
-     * navigable map when iterating over any of its collection views, or the
+     * navigable map when traversing any of its collection views, or the
      * collections views of any of its {@code subMap}, {@code headMap} or
-     * {@code tailMap} views.
+     * {@code tailMap} views, via {@link Iterator}, {@link Spliterator} or
+     * {@link Stream}:
      * <pre>
      *  NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
      *      ...
--- a/jdk/src/java.base/share/classes/java/util/Formatter.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Formatter.java	Wed Jul 05 21:00:20 2017 +0200
@@ -49,6 +49,7 @@
 import java.text.NumberFormat;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.Objects;
 
 import java.time.DateTimeException;
 import java.time.Instant;
@@ -3860,7 +3861,7 @@
                     ampm = dfs.getAmPmStrings();
                 }
                 String s = ampm[t.get(Calendar.AM_PM)];
-                sb.append(s.toLowerCase(l != null ? l : Locale.US));
+                sb.append(s.toLowerCase(Objects.requireNonNullElse(l, Locale.US)));
                 break;
             }
             case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
@@ -3893,7 +3894,7 @@
                 TimeZone tz = t.getTimeZone();
                 sb.append(tz.getDisplayName((t.get(Calendar.DST_OFFSET) != 0),
                                            TimeZone.SHORT,
-                                            (l == null) ? Locale.US : l));
+                                           Objects.requireNonNullElse(l, Locale.US)));
                 break;
             }
 
@@ -3901,7 +3902,7 @@
             case DateTime.NAME_OF_DAY_ABBREV:     // 'a'
             case DateTime.NAME_OF_DAY:          { // 'A'
                 int i = t.get(Calendar.DAY_OF_WEEK);
-                Locale lt = ((l == null) ? Locale.US : l);
+                Locale lt = Objects.requireNonNullElse(l, Locale.US);
                 DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
                 if (c == DateTime.NAME_OF_DAY)
                     sb.append(dfs.getWeekdays()[i]);
@@ -3913,7 +3914,7 @@
             case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
             case DateTime.NAME_OF_MONTH:        { // 'B'
                 int i = t.get(Calendar.MONTH);
-                Locale lt = ((l == null) ? Locale.US : l);
+                Locale lt = Objects.requireNonNullElse(l, Locale.US);
                 DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
                 if (c == DateTime.NAME_OF_MONTH)
                     sb.append(dfs.getMonths()[i]);
@@ -3984,7 +3985,7 @@
                 StringBuilder tsb = new StringBuilder();
                 print(tsb, t, DateTime.AM_PM, l);
 
-                sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US));
+                sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, Locale.US)));
                 break;
             }
             case DateTime.DATE_TIME:    { // 'c' (Sat Nov 04 12:02:33 EST 1999)
@@ -4092,7 +4093,7 @@
                         ampm = dfs.getAmPmStrings();
                     }
                     String s = ampm[t.get(ChronoField.AMPM_OF_DAY)];
-                    sb.append(s.toLowerCase(l != null ? l : Locale.US));
+                    sb.append(s.toLowerCase(Objects.requireNonNullElse(l, Locale.US)));
                     break;
                 }
                 case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
@@ -4131,7 +4132,7 @@
                         sb.append(TimeZone.getTimeZone(zid.getId())
                                           .getDisplayName(zid.getRules().isDaylightSavings(instant),
                                                           TimeZone.SHORT,
-                                                          (l == null) ? Locale.US : l));
+                                                          Objects.requireNonNullElse(l, Locale.US)));
                         break;
                     }
                     sb.append(zid.getId());
@@ -4141,7 +4142,7 @@
                 case DateTime.NAME_OF_DAY_ABBREV:     // 'a'
                 case DateTime.NAME_OF_DAY:          { // 'A'
                     int i = t.get(ChronoField.DAY_OF_WEEK) % 7 + 1;
-                    Locale lt = ((l == null) ? Locale.US : l);
+                    Locale lt = Objects.requireNonNullElse(l, Locale.US);
                     DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
                     if (c == DateTime.NAME_OF_DAY)
                         sb.append(dfs.getWeekdays()[i]);
@@ -4153,7 +4154,7 @@
                 case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
                 case DateTime.NAME_OF_MONTH:        { // 'B'
                     int i = t.get(ChronoField.MONTH_OF_YEAR) - 1;
-                    Locale lt = ((l == null) ? Locale.US : l);
+                    Locale lt = Objects.requireNonNullElse(l, Locale.US);
                     DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
                     if (c == DateTime.NAME_OF_MONTH)
                         sb.append(dfs.getMonths()[i]);
@@ -4223,7 +4224,7 @@
                     // this may be in wrong place for some locales
                     StringBuilder tsb = new StringBuilder();
                     print(tsb, t, DateTime.AM_PM, l);
-                    sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US));
+                    sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, Locale.US)));
                     break;
                 }
                 case DateTime.DATE_TIME:    { // 'c' (Sat Nov 04 12:02:33 EST 1999)
--- a/jdk/src/java.base/share/classes/java/util/Objects.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Objects.java	Wed Jul 05 21:00:20 2017 +0200
@@ -295,7 +295,7 @@
      *        {@code defaultObj} is {@code null}
      * @since 9
      */
-    public static <T> T nonNullElse(T obj, T defaultObj) {
+    public static <T> T requireNonNullElse(T obj, T defaultObj) {
         return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
     }
 
@@ -314,8 +314,9 @@
      *        the {@code supplier.get()} value is {@code null}
      * @since 9
      */
-    public static <T> T nonNullElseGet(T obj, Supplier<? extends T> supplier) {
-        return (obj != null) ? obj : requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()");
+    public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier) {
+        return (obj != null) ? obj
+                : requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()");
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/Random.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Random.java	Wed Jul 05 21:00:20 2017 +0200
@@ -34,7 +34,7 @@
 import java.util.stream.LongStream;
 import java.util.stream.StreamSupport;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * An instance of this class is used to generate a stream of
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Wed Jul 05 21:00:20 2017 +0200
@@ -2775,7 +2775,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long RESULT;
     private static final long STACK;
     private static final long NEXT;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Wed Jul 05 21:00:20 2017 +0200
@@ -297,7 +297,7 @@
      * Table accesses require volatile/atomic reads, writes, and
      * CASes.  Because there is no other way to arrange this without
      * adding further indirections, we use intrinsics
-     * (sun.misc.Unsafe) operations.
+     * (jdk.internal.misc.Unsafe) operations.
      *
      * We use the top (sign) bit of Node hash fields for control
      * purposes -- it is available anyway because of addressing
@@ -3287,7 +3287,7 @@
             return true;
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long LOCKSTATE;
         static {
             try {
@@ -6330,7 +6330,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long SIZECTL;
     private static final long TRANSFERINDEX;
     private static final long BASECOUNT;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Wed Jul 05 21:00:20 2017 +0200
@@ -326,7 +326,7 @@
 
         // Unsafe mechanics
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long PREV;
         private static final long ITEM;
         private static final long NEXT;
@@ -1608,7 +1608,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long HEAD;
     private static final long TAIL;
     static {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -929,7 +929,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long HEAD;
     private static final long TAIL;
     private static final long ITEM;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Wed Jul 05 21:00:20 2017 +0200
@@ -534,7 +534,7 @@
 
         // Unsafe mechanics
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long VALUE;
         private static final long NEXT;
 
@@ -614,7 +614,7 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long RIGHT;
         static {
             try {
@@ -3596,7 +3596,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long HEAD;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Wed Jul 05 21:00:20 2017 +0200
@@ -510,7 +510,7 @@
         U.putObjectVolatile(this, MAP, map);
     }
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long MAP;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1545,7 +1545,7 @@
     private void resetLock() {
         U.putObjectVolatile(this, LOCK, new Object());
     }
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long LOCK;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Wed Jul 05 21:00:20 2017 +0200
@@ -754,7 +754,7 @@
     protected void setRawResult(T t) { }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long PENDING;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Wed Jul 05 21:00:20 2017 +0200
@@ -625,7 +625,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long BOUND;
     private static final long SLOT;
     private static final long MATCH;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1337,7 +1337,7 @@
         }
 
         // Unsafe mechanics. Note that some are (and must be) the same as in FJP
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long QLOCK;
         private static final int ABASE;
         private static final int ASHIFT;
@@ -3452,7 +3452,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long CTL;
     private static final long RUNSTATE;
     private static final int ABASE;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1517,7 +1517,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATUS;
 
     static {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Wed Jul 05 21:00:20 2017 +0200
@@ -185,7 +185,7 @@
     }
 
     // Set up to allow setting thread fields in constructor
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long THREADLOCALS;
     private static final long INHERITABLETHREADLOCALS;
     private static final long INHERITEDACCESSCONTROLCONTEXT;
@@ -248,7 +248,7 @@
          */
         private static ThreadGroup createThreadGroup() {
             try {
-                sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();
+                jdk.internal.misc.Unsafe u = jdk.internal.misc.Unsafe.getUnsafe();
                 long tg = u.objectFieldOffset
                     (Thread.class.getDeclaredField("group"));
                 long gp = u.objectFieldOffset
--- a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Wed Jul 05 21:00:20 2017 +0200
@@ -484,7 +484,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long RUNNER;
     private static final long WAITERS;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -538,7 +538,7 @@
         private static final long serialVersionUID = -3375979862319811754L;
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long ITEM;
         private static final long NEXT;
         private static final long WAITER;
@@ -1564,7 +1564,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long HEAD;
     private static final long TAIL;
     private static final long SWEEPVOTES;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1137,7 +1137,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1010,7 +1010,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long ALLOCATIONSPINLOCK;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1596,7 +1596,7 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long CTL;
         private static final long TAIL;
         private static final long HEAD;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Wed Jul 05 21:00:20 2017 +0200
@@ -283,7 +283,7 @@
             }
 
             // Unsafe mechanics
-            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+            private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
             private static final long MATCH;
             private static final long NEXT;
 
@@ -509,7 +509,7 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long HEAD;
         static {
             try {
@@ -575,7 +575,7 @@
             }
 
             // Unsafe mechanics
-            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+            private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
             private static final long ITEM;
             private static final long NEXT;
 
@@ -817,7 +817,7 @@
             }
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long HEAD;
         private static final long TAIL;
         private static final long CLEANME;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1050,7 +1050,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long SEED;
     private static final long PROBE;
     private static final long SECONDARY;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Wed Jul 05 21:00:20 2017 +0200
@@ -49,7 +49,7 @@
 public class AtomicBoolean implements java.io.Serializable {
     private static final long serialVersionUID = 4654671469794556979L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long VALUE;
 
     static {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Wed Jul 05 21:00:20 2017 +0200
@@ -54,7 +54,7 @@
 public class AtomicInteger extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 6214790243416807050L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long VALUE;
 
     static {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Wed Jul 05 21:00:20 2017 +0200
@@ -49,7 +49,7 @@
 public class AtomicIntegerArray implements java.io.Serializable {
     private static final long serialVersionUID = 2862133569453604235L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final int ABASE;
     private static final int ASHIFT;
     private final int[] array;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Wed Jul 05 21:00:20 2017 +0200
@@ -367,7 +367,7 @@
      */
     private static class AtomicIntegerFieldUpdaterImpl<T>
             extends AtomicIntegerFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private final long offset;
         private final Class<T> tclass;
         private final Class<?> cclass;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Wed Jul 05 21:00:20 2017 +0200
@@ -54,7 +54,7 @@
 public class AtomicLong extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 1927816293512124184L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long VALUE;
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Wed Jul 05 21:00:20 2017 +0200
@@ -48,7 +48,7 @@
 public class AtomicLongArray implements java.io.Serializable {
     private static final long serialVersionUID = -2308431214976778248L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final int ABASE;
     private static final int ASHIFT;
     private final long[] array;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Wed Jul 05 21:00:20 2017 +0200
@@ -366,7 +366,7 @@
     }
 
     private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private final long offset;
         private final Class<T> tclass;
         private final Class<?> cclass;
@@ -490,7 +490,7 @@
 
 
     private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private final long offset;
         private final Class<T> tclass;
         private final Class<?> cclass;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java	Wed Jul 05 21:00:20 2017 +0200
@@ -190,7 +190,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long PAIR;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Wed Jul 05 21:00:20 2017 +0200
@@ -49,7 +49,7 @@
 public class AtomicReference<V> implements java.io.Serializable {
     private static final long serialVersionUID = -1848883965231344442L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long VALUE;
 
     static {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Wed Jul 05 21:00:20 2017 +0200
@@ -52,7 +52,7 @@
 public class AtomicReferenceArray<E> implements java.io.Serializable {
     private static final long serialVersionUID = -6209656149925076980L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long ARRAY;
     private static final int ABASE;
     private static final int ASHIFT;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Wed Jul 05 21:00:20 2017 +0200
@@ -284,7 +284,7 @@
 
     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
         extends AtomicReferenceFieldUpdater<T,V> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private final long offset;
         private final Class<T> tclass;
         private final Class<V> vclass;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java	Wed Jul 05 21:00:20 2017 +0200
@@ -190,7 +190,7 @@
 
     // Unsafe mechanics
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long PAIR;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java	Wed Jul 05 21:00:20 2017 +0200
@@ -133,7 +133,7 @@
         }
 
         // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long VALUE;
         static {
             try {
@@ -372,7 +372,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long BASE;
     private static final long CELLSBUSY;
     private static final long PROBE;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1821,7 +1821,7 @@
      * are at it, we do the same for other CASable fields (which could
      * otherwise be done with atomic field updaters).
      */
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long HEAD;
     private static final long TAIL;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -524,7 +524,7 @@
             return U.compareAndSwapObject(this, NEXT, expect, update);
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
         private static final long NEXT;
         static final long PREV;
         private static final long THREAD;
@@ -2285,7 +2285,7 @@
      * are at it, we do the same for other CASable fields (which could
      * otherwise be done with atomic field updaters).
      */
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long HEAD;
     private static final long TAIL;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Wed Jul 05 21:00:20 2017 +0200
@@ -394,7 +394,7 @@
     }
 
     // Hotspot implementation via intrinsics API
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long PARKBLOCKER;
     private static final long SECONDARY;
     static {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1501,7 +1501,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long TID;
     static {
         try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1398,7 +1398,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
     private static final long STATE;
     private static final long WHEAD;
     private static final long WTAIL;
--- a/jdk/src/java.base/share/classes/java/util/zip/CRC32C.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/java/util/zip/CRC32C.java	Wed Jul 05 21:00:20 2017 +0200
@@ -28,7 +28,7 @@
 import java.nio.ByteOrder;
 
 import jdk.internal.HotSpotIntrinsicCandidate;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.nio.ch.DirectBuffer;
 
 /**
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,7 +30,7 @@
 import java.io.FileDescriptor;
 import java.security.ProtectionDomain;
 import java.security.AccessController;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /** A repository of "shared secrets", which are a mechanism for
     calling implementation-private methods in another package without
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,1391 @@
+/*
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.lang.reflect.Field;
+import java.security.ProtectionDomain;
+
+import sun.reflect.CallerSensitive;
+import sun.reflect.Reflection;
+import sun.misc.VM;
+
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+
+/**
+ * A collection of methods for performing low-level, unsafe operations.
+ * Although the class and all methods are public, use of this class is
+ * limited because only trusted code can obtain instances of it.
+ *
+ * @author John R. Rose
+ * @see #getUnsafe
+ */
+
+public final class Unsafe {
+
+    private static native void registerNatives();
+    static {
+        registerNatives();
+        sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
+    }
+
+    private Unsafe() {}
+
+    private static final Unsafe theUnsafe = new Unsafe();
+
+    /**
+     * Provides the caller with the capability of performing unsafe
+     * operations.
+     *
+     * <p>The returned {@code Unsafe} object should be carefully guarded
+     * by the caller, since it can be used to read and write data at arbitrary
+     * memory addresses.  It must never be passed to untrusted code.
+     *
+     * <p>Most methods in this class are very low-level, and correspond to a
+     * small number of hardware instructions (on typical machines).  Compilers
+     * are encouraged to optimize these methods accordingly.
+     *
+     * <p>Here is a suggested idiom for using unsafe operations:
+     *
+     * <pre> {@code
+     * class MyTrustedClass {
+     *   private static final Unsafe unsafe = Unsafe.getUnsafe();
+     *   ...
+     *   private long myCountAddress = ...;
+     *   public int getCount() { return unsafe.getByte(myCountAddress); }
+     * }}</pre>
+     *
+     * (It may assist compilers to make the local variable {@code final}.)
+     *
+     * @throws  SecurityException  if a security manager exists and its
+     *          {@code checkPropertiesAccess} method doesn't allow
+     *          access to the system properties.
+     */
+    @CallerSensitive
+    public static Unsafe getUnsafe() {
+        Class<?> caller = Reflection.getCallerClass();
+        if (!VM.isSystemDomainLoader(caller.getClassLoader()))
+            throw new SecurityException("Unsafe");
+        return theUnsafe;
+    }
+
+    /// peek and poke operations
+    /// (compilers should optimize these to memory ops)
+
+    // These work on object fields in the Java heap.
+    // They will not work on elements of packed arrays.
+
+    /**
+     * Fetches a value from a given Java variable.
+     * More specifically, fetches a field or array element within the given
+     * object {@code o} at the given offset, or (if {@code o} is null)
+     * from the memory address whose numerical value is the given offset.
+     * <p>
+     * The results are undefined unless one of the following cases is true:
+     * <ul>
+     * <li>The offset was obtained from {@link #objectFieldOffset} on
+     * the {@link java.lang.reflect.Field} of some Java field and the object
+     * referred to by {@code o} is of a class compatible with that
+     * field's class.
+     *
+     * <li>The offset and object reference {@code o} (either null or
+     * non-null) were both obtained via {@link #staticFieldOffset}
+     * and {@link #staticFieldBase} (respectively) from the
+     * reflective {@link Field} representation of some Java field.
+     *
+     * <li>The object referred to by {@code o} is an array, and the offset
+     * is an integer of the form {@code B+N*S}, where {@code N} is
+     * a valid index into the array, and {@code B} and {@code S} are
+     * the values obtained by {@link #arrayBaseOffset} and {@link
+     * #arrayIndexScale} (respectively) from the array's class.  The value
+     * referred to is the {@code N}<em>th</em> element of the array.
+     *
+     * </ul>
+     * <p>
+     * If one of the above cases is true, the call references a specific Java
+     * variable (field or array element).  However, the results are undefined
+     * if that variable is not in fact of the type returned by this method.
+     * <p>
+     * This method refers to a variable by means of two parameters, and so
+     * it provides (in effect) a <em>double-register</em> addressing mode
+     * for Java variables.  When the object reference is null, this method
+     * uses its offset as an absolute address.  This is similar in operation
+     * to methods such as {@link #getInt(long)}, which provide (in effect) a
+     * <em>single-register</em> addressing mode for non-Java variables.
+     * However, because Java variables may have a different layout in memory
+     * from non-Java variables, programmers should not assume that these
+     * two addressing modes are ever equivalent.  Also, programmers should
+     * remember that offsets from the double-register addressing mode cannot
+     * be portably confused with longs used in the single-register addressing
+     * mode.
+     *
+     * @param o Java heap object in which the variable resides, if any, else
+     *        null
+     * @param offset indication of where the variable resides in a Java heap
+     *        object, if any, else a memory address locating the variable
+     *        statically
+     * @return the value fetched from the indicated Java variable
+     * @throws RuntimeException No defined exceptions are thrown, not even
+     *         {@link NullPointerException}
+     */
+    @HotSpotIntrinsicCandidate
+    public native int getInt(Object o, long offset);
+
+    /**
+     * Stores a value into a given Java variable.
+     * <p>
+     * The first two parameters are interpreted exactly as with
+     * {@link #getInt(Object, long)} to refer to a specific
+     * Java variable (field or array element).  The given value
+     * is stored into that variable.
+     * <p>
+     * The variable must be of the same type as the method
+     * parameter {@code x}.
+     *
+     * @param o Java heap object in which the variable resides, if any, else
+     *        null
+     * @param offset indication of where the variable resides in a Java heap
+     *        object, if any, else a memory address locating the variable
+     *        statically
+     * @param x the value to store into the indicated Java variable
+     * @throws RuntimeException No defined exceptions are thrown, not even
+     *         {@link NullPointerException}
+     */
+    @HotSpotIntrinsicCandidate
+    public native void putInt(Object o, long offset, int x);
+
+    /**
+     * Fetches a reference value from a given Java variable.
+     * @see #getInt(Object, long)
+     */
+    @HotSpotIntrinsicCandidate
+    public native Object getObject(Object o, long offset);
+
+    /**
+     * Stores a reference value into a given Java variable.
+     * <p>
+     * Unless the reference {@code x} being stored is either null
+     * or matches the field type, the results are undefined.
+     * If the reference {@code o} is non-null, card marks or
+     * other store barriers for that object (if the VM requires them)
+     * are updated.
+     * @see #putInt(Object, long, int)
+     */
+    @HotSpotIntrinsicCandidate
+    public native void putObject(Object o, long offset, Object x);
+
+    /** @see #getInt(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public native boolean getBoolean(Object o, long offset);
+    /** @see #putInt(Object, long, int) */
+    @HotSpotIntrinsicCandidate
+    public native void    putBoolean(Object o, long offset, boolean x);
+    /** @see #getInt(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public native byte    getByte(Object o, long offset);
+    /** @see #putInt(Object, long, int) */
+    @HotSpotIntrinsicCandidate
+    public native void    putByte(Object o, long offset, byte x);
+    /** @see #getInt(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public native short   getShort(Object o, long offset);
+    /** @see #putInt(Object, long, int) */
+    @HotSpotIntrinsicCandidate
+    public native void    putShort(Object o, long offset, short x);
+    /** @see #getInt(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public native char    getChar(Object o, long offset);
+    /** @see #putInt(Object, long, int) */
+    @HotSpotIntrinsicCandidate
+    public native void    putChar(Object o, long offset, char x);
+    /** @see #getInt(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public native long    getLong(Object o, long offset);
+    /** @see #putInt(Object, long, int) */
+    @HotSpotIntrinsicCandidate
+    public native void    putLong(Object o, long offset, long x);
+    /** @see #getInt(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public native float   getFloat(Object o, long offset);
+    /** @see #putInt(Object, long, int) */
+    @HotSpotIntrinsicCandidate
+    public native void    putFloat(Object o, long offset, float x);
+    /** @see #getInt(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public native double  getDouble(Object o, long offset);
+    /** @see #putInt(Object, long, int) */
+    @HotSpotIntrinsicCandidate
+    public native void    putDouble(Object o, long offset, double x);
+
+    // These read VM internal data.
+
+    /**
+     * Fetches an uncompressed reference value from a given native variable
+     * ignoring the VM's compressed references mode.
+     *
+     * @param address a memory address locating the variable
+     * @return the value fetched from the indicated native variable
+     */
+    public native Object getUncompressedObject(long address);
+
+    /**
+     * Fetches the {@link java.lang.Class} Java mirror for the given native
+     * metaspace {@code Klass} pointer.
+     *
+     * @param metaspaceKlass a native metaspace {@code Klass} pointer
+     * @return the {@link java.lang.Class} Java mirror
+     */
+    public native Class<?> getJavaMirror(long metaspaceKlass);
+
+    /**
+     * Fetches a native metaspace {@code Klass} pointer for the given Java
+     * object.
+     *
+     * @param o Java heap object for which to fetch the class pointer
+     * @return a native metaspace {@code Klass} pointer
+     */
+    public native long getKlassPointer(Object o);
+
+    // These work on values in the C heap.
+
+    /**
+     * Fetches a value from a given memory address.  If the address is zero, or
+     * does not point into a block obtained from {@link #allocateMemory}, the
+     * results are undefined.
+     *
+     * @see #allocateMemory
+     */
+    @HotSpotIntrinsicCandidate
+    public native byte    getByte(long address);
+
+    /**
+     * Stores a value into a given memory address.  If the address is zero, or
+     * does not point into a block obtained from {@link #allocateMemory}, the
+     * results are undefined.
+     *
+     * @see #getByte(long)
+     */
+    @HotSpotIntrinsicCandidate
+    public native void    putByte(long address, byte x);
+
+    /** @see #getByte(long) */
+    @HotSpotIntrinsicCandidate
+    public native short   getShort(long address);
+    /** @see #putByte(long, byte) */
+    @HotSpotIntrinsicCandidate
+    public native void    putShort(long address, short x);
+    /** @see #getByte(long) */
+    @HotSpotIntrinsicCandidate
+    public native char    getChar(long address);
+    /** @see #putByte(long, byte) */
+    @HotSpotIntrinsicCandidate
+    public native void    putChar(long address, char x);
+    /** @see #getByte(long) */
+    @HotSpotIntrinsicCandidate
+    public native int     getInt(long address);
+    /** @see #putByte(long, byte) */
+    @HotSpotIntrinsicCandidate
+    public native void    putInt(long address, int x);
+    /** @see #getByte(long) */
+    @HotSpotIntrinsicCandidate
+    public native long    getLong(long address);
+    /** @see #putByte(long, byte) */
+    @HotSpotIntrinsicCandidate
+    public native void    putLong(long address, long x);
+    /** @see #getByte(long) */
+    @HotSpotIntrinsicCandidate
+    public native float   getFloat(long address);
+    /** @see #putByte(long, byte) */
+    @HotSpotIntrinsicCandidate
+    public native void    putFloat(long address, float x);
+    /** @see #getByte(long) */
+    @HotSpotIntrinsicCandidate
+    public native double  getDouble(long address);
+    /** @see #putByte(long, byte) */
+    @HotSpotIntrinsicCandidate
+    public native void    putDouble(long address, double x);
+
+    /**
+     * Fetches a native pointer from a given memory address.  If the address is
+     * zero, or does not point into a block obtained from {@link
+     * #allocateMemory}, the results are undefined.
+     *
+     * <p>If the native pointer is less than 64 bits wide, it is extended as
+     * an unsigned number to a Java long.  The pointer may be indexed by any
+     * given byte offset, simply by adding that offset (as a simple integer) to
+     * the long representing the pointer.  The number of bytes actually read
+     * from the target address may be determined by consulting {@link
+     * #addressSize}.
+     *
+     * @see #allocateMemory
+     */
+    @HotSpotIntrinsicCandidate
+    public native long getAddress(long address);
+
+    /**
+     * Stores a native pointer into a given memory address.  If the address is
+     * zero, or does not point into a block obtained from {@link
+     * #allocateMemory}, the results are undefined.
+     *
+     * <p>The number of bytes actually written at the target address may be
+     * determined by consulting {@link #addressSize}.
+     *
+     * @see #getAddress(long)
+     */
+    @HotSpotIntrinsicCandidate
+    public native void putAddress(long address, long x);
+
+    /// wrappers for malloc, realloc, free:
+
+    /**
+     * Allocates a new block of native memory, of the given size in bytes.  The
+     * contents of the memory are uninitialized; they will generally be
+     * garbage.  The resulting native pointer will never be zero, and will be
+     * aligned for all value types.  Dispose of this memory by calling {@link
+     * #freeMemory}, or resize it with {@link #reallocateMemory}.
+     *
+     * @throws IllegalArgumentException if the size is negative or too large
+     *         for the native size_t type
+     *
+     * @throws OutOfMemoryError if the allocation is refused by the system
+     *
+     * @see #getByte(long)
+     * @see #putByte(long, byte)
+     */
+    public native long allocateMemory(long bytes);
+
+    /**
+     * Resizes a new block of native memory, to the given size in bytes.  The
+     * contents of the new block past the size of the old block are
+     * uninitialized; they will generally be garbage.  The resulting native
+     * pointer will be zero if and only if the requested size is zero.  The
+     * resulting native pointer will be aligned for all value types.  Dispose
+     * of this memory by calling {@link #freeMemory}, or resize it with {@link
+     * #reallocateMemory}.  The address passed to this method may be null, in
+     * which case an allocation will be performed.
+     *
+     * @throws IllegalArgumentException if the size is negative or too large
+     *         for the native size_t type
+     *
+     * @throws OutOfMemoryError if the allocation is refused by the system
+     *
+     * @see #allocateMemory
+     */
+    public native long reallocateMemory(long address, long bytes);
+
+    /**
+     * Sets all bytes in a given block of memory to a fixed value
+     * (usually zero).
+     *
+     * <p>This method determines a block's base address by means of two parameters,
+     * and so it provides (in effect) a <em>double-register</em> addressing mode,
+     * as discussed in {@link #getInt(Object,long)}.  When the object reference is null,
+     * the offset supplies an absolute base address.
+     *
+     * <p>The stores are in coherent (atomic) units of a size determined
+     * by the address and length parameters.  If the effective address and
+     * length are all even modulo 8, the stores take place in 'long' units.
+     * If the effective address and length are (resp.) even modulo 4 or 2,
+     * the stores take place in units of 'int' or 'short'.
+     *
+     * @since 1.7
+     */
+    public native void setMemory(Object o, long offset, long bytes, byte value);
+
+    /**
+     * Sets all bytes in a given block of memory to a fixed value
+     * (usually zero).  This provides a <em>single-register</em> addressing mode,
+     * as discussed in {@link #getInt(Object,long)}.
+     *
+     * <p>Equivalent to {@code setMemory(null, address, bytes, value)}.
+     */
+    public void setMemory(long address, long bytes, byte value) {
+        setMemory(null, address, bytes, value);
+    }
+
+    /**
+     * Sets all bytes in a given block of memory to a copy of another
+     * block.
+     *
+     * <p>This method determines each block's base address by means of two parameters,
+     * and so it provides (in effect) a <em>double-register</em> addressing mode,
+     * as discussed in {@link #getInt(Object,long)}.  When the object reference is null,
+     * the offset supplies an absolute base address.
+     *
+     * <p>The transfers are in coherent (atomic) units of a size determined
+     * by the address and length parameters.  If the effective addresses and
+     * length are all even modulo 8, the transfer takes place in 'long' units.
+     * If the effective addresses and length are (resp.) even modulo 4 or 2,
+     * the transfer takes place in units of 'int' or 'short'.
+     *
+     * @since 1.7
+     */
+    @HotSpotIntrinsicCandidate
+    public native void copyMemory(Object srcBase, long srcOffset,
+                                  Object destBase, long destOffset,
+                                  long bytes);
+    /**
+     * Sets all bytes in a given block of memory to a copy of another
+     * block.  This provides a <em>single-register</em> addressing mode,
+     * as discussed in {@link #getInt(Object,long)}.
+     *
+     * Equivalent to {@code copyMemory(null, srcAddress, null, destAddress, bytes)}.
+     */
+    public void copyMemory(long srcAddress, long destAddress, long bytes) {
+        copyMemory(null, srcAddress, null, destAddress, bytes);
+    }
+
+    /**
+     * Disposes of a block of native memory, as obtained from {@link
+     * #allocateMemory} or {@link #reallocateMemory}.  The address passed to
+     * this method may be null, in which case no action is taken.
+     *
+     * @see #allocateMemory
+     */
+    public native void freeMemory(long address);
+
+    /// random queries
+
+    /**
+     * This constant differs from all results that will ever be returned from
+     * {@link #staticFieldOffset}, {@link #objectFieldOffset},
+     * or {@link #arrayBaseOffset}.
+     */
+    public static final int INVALID_FIELD_OFFSET   = -1;
+
+    /**
+     * Reports the location of a given field in the storage allocation of its
+     * class.  Do not expect to perform any sort of arithmetic on this offset;
+     * it is just a cookie which is passed to the unsafe heap memory accessors.
+     *
+     * <p>Any given field will always have the same offset and base, and no
+     * two distinct fields of the same class will ever have the same offset
+     * and base.
+     *
+     * <p>As of 1.4.1, offsets for fields are represented as long values,
+     * although the Sun JVM does not use the most significant 32 bits.
+     * However, JVM implementations which store static fields at absolute
+     * addresses can use long offsets and null base pointers to express
+     * the field locations in a form usable by {@link #getInt(Object,long)}.
+     * Therefore, code which will be ported to such JVMs on 64-bit platforms
+     * must preserve all bits of static field offsets.
+     * @see #getInt(Object, long)
+     */
+    public native long objectFieldOffset(Field f);
+
+    /**
+     * Reports the location of a given static field, in conjunction with {@link
+     * #staticFieldBase}.
+     * <p>Do not expect to perform any sort of arithmetic on this offset;
+     * it is just a cookie which is passed to the unsafe heap memory accessors.
+     *
+     * <p>Any given field will always have the same offset, and no two distinct
+     * fields of the same class will ever have the same offset.
+     *
+     * <p>As of 1.4.1, offsets for fields are represented as long values,
+     * although the Sun JVM does not use the most significant 32 bits.
+     * It is hard to imagine a JVM technology which needs more than
+     * a few bits to encode an offset within a non-array object,
+     * However, for consistency with other methods in this class,
+     * this method reports its result as a long value.
+     * @see #getInt(Object, long)
+     */
+    public native long staticFieldOffset(Field f);
+
+    /**
+     * Reports the location of a given static field, in conjunction with {@link
+     * #staticFieldOffset}.
+     * <p>Fetch the base "Object", if any, with which static fields of the
+     * given class can be accessed via methods like {@link #getInt(Object,
+     * long)}.  This value may be null.  This value may refer to an object
+     * which is a "cookie", not guaranteed to be a real Object, and it should
+     * not be used in any way except as argument to the get and put routines in
+     * this class.
+     */
+    public native Object staticFieldBase(Field f);
+
+    /**
+     * Detects if the given class may need to be initialized. This is often
+     * needed in conjunction with obtaining the static field base of a
+     * class.
+     * @return false only if a call to {@code ensureClassInitialized} would have no effect
+     */
+    public native boolean shouldBeInitialized(Class<?> c);
+
+    /**
+     * Ensures the given class has been initialized. This is often
+     * needed in conjunction with obtaining the static field base of a
+     * class.
+     */
+    public native void ensureClassInitialized(Class<?> c);
+
+    /**
+     * Reports the offset of the first element in the storage allocation of a
+     * given array class.  If {@link #arrayIndexScale} returns a non-zero value
+     * for the same class, you may use that scale factor, together with this
+     * base offset, to form new offsets to access elements of arrays of the
+     * given class.
+     *
+     * @see #getInt(Object, long)
+     * @see #putInt(Object, long, int)
+     */
+    public native int arrayBaseOffset(Class<?> arrayClass);
+
+    /** The value of {@code arrayBaseOffset(boolean[].class)} */
+    public static final int ARRAY_BOOLEAN_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(boolean[].class);
+
+    /** The value of {@code arrayBaseOffset(byte[].class)} */
+    public static final int ARRAY_BYTE_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(byte[].class);
+
+    /** The value of {@code arrayBaseOffset(short[].class)} */
+    public static final int ARRAY_SHORT_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(short[].class);
+
+    /** The value of {@code arrayBaseOffset(char[].class)} */
+    public static final int ARRAY_CHAR_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(char[].class);
+
+    /** The value of {@code arrayBaseOffset(int[].class)} */
+    public static final int ARRAY_INT_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(int[].class);
+
+    /** The value of {@code arrayBaseOffset(long[].class)} */
+    public static final int ARRAY_LONG_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(long[].class);
+
+    /** The value of {@code arrayBaseOffset(float[].class)} */
+    public static final int ARRAY_FLOAT_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(float[].class);
+
+    /** The value of {@code arrayBaseOffset(double[].class)} */
+    public static final int ARRAY_DOUBLE_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(double[].class);
+
+    /** The value of {@code arrayBaseOffset(Object[].class)} */
+    public static final int ARRAY_OBJECT_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(Object[].class);
+
+    /**
+     * Reports the scale factor for addressing elements in the storage
+     * allocation of a given array class.  However, arrays of "narrow" types
+     * will generally not work properly with accessors like {@link
+     * #getByte(Object, long)}, so the scale factor for such classes is reported
+     * as zero.
+     *
+     * @see #arrayBaseOffset
+     * @see #getInt(Object, long)
+     * @see #putInt(Object, long, int)
+     */
+    public native int arrayIndexScale(Class<?> arrayClass);
+
+    /** The value of {@code arrayIndexScale(boolean[].class)} */
+    public static final int ARRAY_BOOLEAN_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(boolean[].class);
+
+    /** The value of {@code arrayIndexScale(byte[].class)} */
+    public static final int ARRAY_BYTE_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(byte[].class);
+
+    /** The value of {@code arrayIndexScale(short[].class)} */
+    public static final int ARRAY_SHORT_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(short[].class);
+
+    /** The value of {@code arrayIndexScale(char[].class)} */
+    public static final int ARRAY_CHAR_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(char[].class);
+
+    /** The value of {@code arrayIndexScale(int[].class)} */
+    public static final int ARRAY_INT_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(int[].class);
+
+    /** The value of {@code arrayIndexScale(long[].class)} */
+    public static final int ARRAY_LONG_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(long[].class);
+
+    /** The value of {@code arrayIndexScale(float[].class)} */
+    public static final int ARRAY_FLOAT_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(float[].class);
+
+    /** The value of {@code arrayIndexScale(double[].class)} */
+    public static final int ARRAY_DOUBLE_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(double[].class);
+
+    /** The value of {@code arrayIndexScale(Object[].class)} */
+    public static final int ARRAY_OBJECT_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(Object[].class);
+
+    /**
+     * Reports the size in bytes of a native pointer, as stored via {@link
+     * #putAddress}.  This value will be either 4 or 8.  Note that the sizes of
+     * other primitive types (as stored in native memory blocks) is determined
+     * fully by their information content.
+     */
+    public native int addressSize();
+
+    /** The value of {@code addressSize()} */
+    public static final int ADDRESS_SIZE = theUnsafe.addressSize();
+
+    /**
+     * Reports the size in bytes of a native memory page (whatever that is).
+     * This value will always be a power of two.
+     */
+    public native int pageSize();
+
+
+    /// random trusted operations from JNI:
+
+    /**
+     * Tells the VM to define a class, without security checks.  By default, the
+     * class loader and protection domain come from the caller's class.
+     */
+    public native Class<?> defineClass(String name, byte[] b, int off, int len,
+                                       ClassLoader loader,
+                                       ProtectionDomain protectionDomain);
+
+    /**
+     * Defines a class but does not make it known to the class loader or system dictionary.
+     * <p>
+     * For each CP entry, the corresponding CP patch must either be null or have
+     * the a format that matches its tag:
+     * <ul>
+     * <li>Integer, Long, Float, Double: the corresponding wrapper object type from java.lang
+     * <li>Utf8: a string (must have suitable syntax if used as signature or name)
+     * <li>Class: any java.lang.Class object
+     * <li>String: any object (not just a java.lang.String)
+     * <li>InterfaceMethodRef: (NYI) a method handle to invoke on that call site's arguments
+     * </ul>
+     * @param hostClass context for linkage, access control, protection domain, and class loader
+     * @param data      bytes of a class file
+     * @param cpPatches where non-null entries exist, they replace corresponding CP entries in data
+     */
+    public native Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches);
+
+    /**
+     * Allocates an instance but does not run any constructor.
+     * Initializes the class if it has not yet been.
+     */
+    @HotSpotIntrinsicCandidate
+    public native Object allocateInstance(Class<?> cls)
+        throws InstantiationException;
+
+    /** Throws the exception without telling the verifier. */
+    public native void throwException(Throwable ee);
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @HotSpotIntrinsicCandidate
+    public final native boolean compareAndSwapObject(Object o, long offset,
+                                                     Object expected,
+                                                     Object x);
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @HotSpotIntrinsicCandidate
+    public final native boolean compareAndSwapInt(Object o, long offset,
+                                                  int expected,
+                                                  int x);
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @HotSpotIntrinsicCandidate
+    public final native boolean compareAndSwapLong(Object o, long offset,
+                                                   long expected,
+                                                   long x);
+
+    /**
+     * Fetches a reference value from a given Java variable, with volatile
+     * load semantics. Otherwise identical to {@link #getObject(Object, long)}
+     */
+    @HotSpotIntrinsicCandidate
+    public native Object getObjectVolatile(Object o, long offset);
+
+    /**
+     * Stores a reference value into a given Java variable, with
+     * volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)}
+     */
+    @HotSpotIntrinsicCandidate
+    public native void    putObjectVolatile(Object o, long offset, Object x);
+
+    /** Volatile version of {@link #getInt(Object, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native int     getIntVolatile(Object o, long offset);
+
+    /** Volatile version of {@link #putInt(Object, long, int)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putIntVolatile(Object o, long offset, int x);
+
+    /** Volatile version of {@link #getBoolean(Object, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native boolean getBooleanVolatile(Object o, long offset);
+
+    /** Volatile version of {@link #putBoolean(Object, long, boolean)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putBooleanVolatile(Object o, long offset, boolean x);
+
+    /** Volatile version of {@link #getByte(Object, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native byte    getByteVolatile(Object o, long offset);
+
+    /** Volatile version of {@link #putByte(Object, long, byte)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putByteVolatile(Object o, long offset, byte x);
+
+    /** Volatile version of {@link #getShort(Object, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native short   getShortVolatile(Object o, long offset);
+
+    /** Volatile version of {@link #putShort(Object, long, short)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putShortVolatile(Object o, long offset, short x);
+
+    /** Volatile version of {@link #getChar(Object, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native char    getCharVolatile(Object o, long offset);
+
+    /** Volatile version of {@link #putChar(Object, long, char)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putCharVolatile(Object o, long offset, char x);
+
+    /** Volatile version of {@link #getLong(Object, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native long    getLongVolatile(Object o, long offset);
+
+    /** Volatile version of {@link #putLong(Object, long, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putLongVolatile(Object o, long offset, long x);
+
+    /** Volatile version of {@link #getFloat(Object, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native float   getFloatVolatile(Object o, long offset);
+
+    /** Volatile version of {@link #putFloat(Object, long, float)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putFloatVolatile(Object o, long offset, float x);
+
+    /** Volatile version of {@link #getDouble(Object, long)}  */
+    @HotSpotIntrinsicCandidate
+    public native double  getDoubleVolatile(Object o, long offset);
+
+    /** Volatile version of {@link #putDouble(Object, long, double)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putDoubleVolatile(Object o, long offset, double x);
+
+    /**
+     * Version of {@link #putObjectVolatile(Object, long, Object)}
+     * that does not guarantee immediate visibility of the store to
+     * other threads. This method is generally only useful if the
+     * underlying field is a Java volatile (or if an array cell, one
+     * that is otherwise only accessed using volatile accesses).
+     *
+     * Corresponds to C11 atomic_store_explicit(..., memory_order_release).
+     */
+    @HotSpotIntrinsicCandidate
+    public native void    putOrderedObject(Object o, long offset, Object x);
+
+    /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)}  */
+    @HotSpotIntrinsicCandidate
+    public native void    putOrderedInt(Object o, long offset, int x);
+
+    /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
+    @HotSpotIntrinsicCandidate
+    public native void    putOrderedLong(Object o, long offset, long x);
+
+    /**
+     * Unblocks the given thread blocked on {@code park}, or, if it is
+     * not blocked, causes the subsequent call to {@code park} not to
+     * block.  Note: this operation is "unsafe" solely because the
+     * caller must somehow ensure that the thread has not been
+     * destroyed. Nothing special is usually required to ensure this
+     * when called from Java (in which there will ordinarily be a live
+     * reference to the thread) but this is not nearly-automatically
+     * so when calling from native code.
+     *
+     * @param thread the thread to unpark.
+     */
+    @HotSpotIntrinsicCandidate
+    public native void unpark(Object thread);
+
+    /**
+     * Blocks current thread, returning when a balancing
+     * {@code unpark} occurs, or a balancing {@code unpark} has
+     * already occurred, or the thread is interrupted, or, if not
+     * absolute and time is not zero, the given time nanoseconds have
+     * elapsed, or if absolute, the given deadline in milliseconds
+     * since Epoch has passed, or spuriously (i.e., returning for no
+     * "reason"). Note: This operation is in the Unsafe class only
+     * because {@code unpark} is, so it would be strange to place it
+     * elsewhere.
+     */
+    @HotSpotIntrinsicCandidate
+    public native void park(boolean isAbsolute, long time);
+
+    /**
+     * Gets the load average in the system run queue assigned
+     * to the available processors averaged over various periods of time.
+     * This method retrieves the given {@code nelem} samples and
+     * assigns to the elements of the given {@code loadavg} array.
+     * The system imposes a maximum of 3 samples, representing
+     * averages over the last 1,  5,  and  15 minutes, respectively.
+     *
+     * @param loadavg an array of double of size nelems
+     * @param nelems the number of samples to be retrieved and
+     *        must be 1 to 3.
+     *
+     * @return the number of samples actually retrieved; or -1
+     *         if the load average is unobtainable.
+     */
+    public native int getLoadAverage(double[] loadavg, int nelems);
+
+    // The following contain CAS-based Java implementations used on
+    // platforms not supporting native instructions
+
+    /**
+     * Atomically adds the given value to the current value of a field
+     * or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param delta the value to add
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final int getAndAddInt(Object o, long offset, int delta) {
+        int v;
+        do {
+            v = getIntVolatile(o, offset);
+        } while (!compareAndSwapInt(o, offset, v, v + delta));
+        return v;
+    }
+
+    /**
+     * Atomically adds the given value to the current value of a field
+     * or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param delta the value to add
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final long getAndAddLong(Object o, long offset, long delta) {
+        long v;
+        do {
+            v = getLongVolatile(o, offset);
+        } while (!compareAndSwapLong(o, offset, v, v + delta));
+        return v;
+    }
+
+    /**
+     * Atomically exchanges the given value with the current value of
+     * a field or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final int getAndSetInt(Object o, long offset, int newValue) {
+        int v;
+        do {
+            v = getIntVolatile(o, offset);
+        } while (!compareAndSwapInt(o, offset, v, newValue));
+        return v;
+    }
+
+    /**
+     * Atomically exchanges the given value with the current value of
+     * a field or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final long getAndSetLong(Object o, long offset, long newValue) {
+        long v;
+        do {
+            v = getLongVolatile(o, offset);
+        } while (!compareAndSwapLong(o, offset, v, newValue));
+        return v;
+    }
+
+    /**
+     * Atomically exchanges the given reference value with the current
+     * reference value of a field or array element within the given
+     * object {@code o} at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final Object getAndSetObject(Object o, long offset, Object newValue) {
+        Object v;
+        do {
+            v = getObjectVolatile(o, offset);
+        } while (!compareAndSwapObject(o, offset, v, newValue));
+        return v;
+    }
+
+
+    /**
+     * Ensures that loads before the fence will not be reordered with loads and
+     * stores after the fence; a "LoadLoad plus LoadStore barrier".
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_acquire)
+     * (an "acquire fence").
+     *
+     * A pure LoadLoad fence is not provided, since the addition of LoadStore
+     * is almost always desired, and most current hardware instructions that
+     * provide a LoadLoad barrier also provide a LoadStore barrier for free.
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public native void loadFence();
+
+    /**
+     * Ensures that loads and stores before the fence will not be reordered with
+     * stores after the fence; a "StoreStore plus LoadStore barrier".
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_release)
+     * (a "release fence").
+     *
+     * A pure StoreStore fence is not provided, since the addition of LoadStore
+     * is almost always desired, and most current hardware instructions that
+     * provide a StoreStore barrier also provide a LoadStore barrier for free.
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public native void storeFence();
+
+    /**
+     * Ensures that loads and stores before the fence will not be reordered
+     * with loads and stores after the fence.  Implies the effects of both
+     * loadFence() and storeFence(), and in addition, the effect of a StoreLoad
+     * barrier.
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst).
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public native void fullFence();
+
+    /**
+     * Throws IllegalAccessError; for use by the VM for access control
+     * error support.
+     * @since 1.8
+     */
+    private static void throwIllegalAccessError() {
+        throw new IllegalAccessError();
+    }
+
+    /**
+     * @return Returns true if the native byte ordering of this
+     * platform is big-endian, false if it is little-endian.
+     */
+    public final boolean isBigEndian() { return BE; }
+
+    /**
+     * @return Returns true if this platform is capable of performing
+     * accesses at addresses which are not aligned for the type of the
+     * primitive type being accessed, false otherwise.
+     */
+    public final boolean unalignedAccess() { return unalignedAccess; }
+
+    /**
+     * Fetches a value at some byte offset into a given Java object.
+     * More specifically, fetches a value within the given object
+     * <code>o</code> at the given offset, or (if <code>o</code> is
+     * null) from the memory address whose numerical value is the
+     * given offset.  <p>
+     *
+     * The specification of this method is the same as {@link
+     * #getLong(Object, long)} except that the offset does not need to
+     * have been obtained from {@link #objectFieldOffset} on the
+     * {@link java.lang.reflect.Field} of some Java field.  The value
+     * in memory is raw data, and need not correspond to any Java
+     * variable.  Unless <code>o</code> is null, the value accessed
+     * must be entirely within the allocated object.  The endianness
+     * of the value in memory is the endianness of the native platform.
+     *
+     * <p> The read will be atomic with respect to the largest power
+     * of two that divides the GCD of the offset and the storage size.
+     * For example, getLongUnaligned will make atomic reads of 2-, 4-,
+     * or 8-byte storage units if the offset is zero mod 2, 4, or 8,
+     * respectively.  There are no other guarantees of atomicity.
+     * <p>
+     * 8-byte atomicity is only guaranteed on platforms on which
+     * support atomic accesses to longs.
+     *
+     * @param o Java heap object in which the value resides, if any, else
+     *        null
+     * @param offset The offset in bytes from the start of the object
+     * @return the value fetched from the indicated object
+     * @throws RuntimeException No defined exceptions are thrown, not even
+     *         {@link NullPointerException}
+     * @since 1.9
+     */
+    @HotSpotIntrinsicCandidate
+    public final long getLongUnaligned(Object o, long offset) {
+        if ((offset & 7) == 0) {
+            return getLong(o, offset);
+        } else if ((offset & 3) == 0) {
+            return makeLong(getInt(o, offset),
+                            getInt(o, offset + 4));
+        } else if ((offset & 1) == 0) {
+            return makeLong(getShort(o, offset),
+                            getShort(o, offset + 2),
+                            getShort(o, offset + 4),
+                            getShort(o, offset + 6));
+        } else {
+            return makeLong(getByte(o, offset),
+                            getByte(o, offset + 1),
+                            getByte(o, offset + 2),
+                            getByte(o, offset + 3),
+                            getByte(o, offset + 4),
+                            getByte(o, offset + 5),
+                            getByte(o, offset + 6),
+                            getByte(o, offset + 7));
+        }
+    }
+    /**
+     * As {@link #getLongUnaligned(Object, long)} but with an
+     * additional argument which specifies the endianness of the value
+     * as stored in memory.
+     *
+     * @param o Java heap object in which the variable resides
+     * @param offset The offset in bytes from the start of the object
+     * @param bigEndian The endianness of the value
+     * @return the value fetched from the indicated object
+     * @since 1.9
+     */
+    public final long getLongUnaligned(Object o, long offset, boolean bigEndian) {
+        return convEndian(bigEndian, getLongUnaligned(o, offset));
+    }
+
+    /** @see #getLongUnaligned(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public final int getIntUnaligned(Object o, long offset) {
+        if ((offset & 3) == 0) {
+            return getInt(o, offset);
+        } else if ((offset & 1) == 0) {
+            return makeInt(getShort(o, offset),
+                           getShort(o, offset + 2));
+        } else {
+            return makeInt(getByte(o, offset),
+                           getByte(o, offset + 1),
+                           getByte(o, offset + 2),
+                           getByte(o, offset + 3));
+        }
+    }
+    /** @see #getLongUnaligned(Object, long, boolean) */
+    public final int getIntUnaligned(Object o, long offset, boolean bigEndian) {
+        return convEndian(bigEndian, getIntUnaligned(o, offset));
+    }
+
+    /** @see #getLongUnaligned(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public final short getShortUnaligned(Object o, long offset) {
+        if ((offset & 1) == 0) {
+            return getShort(o, offset);
+        } else {
+            return makeShort(getByte(o, offset),
+                             getByte(o, offset + 1));
+        }
+    }
+    /** @see #getLongUnaligned(Object, long, boolean) */
+    public final short getShortUnaligned(Object o, long offset, boolean bigEndian) {
+        return convEndian(bigEndian, getShortUnaligned(o, offset));
+    }
+
+    /** @see #getLongUnaligned(Object, long) */
+    @HotSpotIntrinsicCandidate
+    public final char getCharUnaligned(Object o, long offset) {
+        return (char)getShortUnaligned(o, offset);
+    }
+
+    /** @see #getLongUnaligned(Object, long, boolean) */
+    public final char getCharUnaligned(Object o, long offset, boolean bigEndian) {
+        return convEndian(bigEndian, getCharUnaligned(o, offset));
+    }
+
+    /**
+     * Stores a value at some byte offset into a given Java object.
+     * <p>
+     * The specification of this method is the same as {@link
+     * #getLong(Object, long)} except that the offset does not need to
+     * have been obtained from {@link #objectFieldOffset} on the
+     * {@link java.lang.reflect.Field} of some Java field.  The value
+     * in memory is raw data, and need not correspond to any Java
+     * variable.  The endianness of the value in memory is the
+     * endianness of the native platform.
+     * <p>
+     * The write will be atomic with respect to the largest power of
+     * two that divides the GCD of the offset and the storage size.
+     * For example, putLongUnaligned will make atomic writes of 2-, 4-,
+     * or 8-byte storage units if the offset is zero mod 2, 4, or 8,
+     * respectively.  There are no other guarantees of atomicity.
+     * <p>
+     * 8-byte atomicity is only guaranteed on platforms on which
+     * support atomic accesses to longs.
+     *
+     * @param o Java heap object in which the value resides, if any, else
+     *        null
+     * @param offset The offset in bytes from the start of the object
+     * @param x the value to store
+     * @throws RuntimeException No defined exceptions are thrown, not even
+     *         {@link NullPointerException}
+     * @since 1.9
+     */
+    @HotSpotIntrinsicCandidate
+    public final void putLongUnaligned(Object o, long offset, long x) {
+        if ((offset & 7) == 0) {
+            putLong(o, offset, x);
+        } else if ((offset & 3) == 0) {
+            putLongParts(o, offset,
+                         (int)(x >> 0),
+                         (int)(x >>> 32));
+        } else if ((offset & 1) == 0) {
+            putLongParts(o, offset,
+                         (short)(x >>> 0),
+                         (short)(x >>> 16),
+                         (short)(x >>> 32),
+                         (short)(x >>> 48));
+        } else {
+            putLongParts(o, offset,
+                         (byte)(x >>> 0),
+                         (byte)(x >>> 8),
+                         (byte)(x >>> 16),
+                         (byte)(x >>> 24),
+                         (byte)(x >>> 32),
+                         (byte)(x >>> 40),
+                         (byte)(x >>> 48),
+                         (byte)(x >>> 56));
+        }
+    }
+
+    /**
+     * As {@link #putLongUnaligned(Object, long, long)} but with an additional
+     * argument which specifies the endianness of the value as stored in memory.
+     * @param o Java heap object in which the value resides
+     * @param offset The offset in bytes from the start of the object
+     * @param x the value to store
+     * @param bigEndian The endianness of the value
+     * @throws RuntimeException No defined exceptions are thrown, not even
+     *         {@link NullPointerException}
+     * @since 1.9
+     */
+    public final void putLongUnaligned(Object o, long offset, long x, boolean bigEndian) {
+        putLongUnaligned(o, offset, convEndian(bigEndian, x));
+    }
+
+    /** @see #putLongUnaligned(Object, long, long) */
+    @HotSpotIntrinsicCandidate
+    public final void putIntUnaligned(Object o, long offset, int x) {
+        if ((offset & 3) == 0) {
+            putInt(o, offset, x);
+        } else if ((offset & 1) == 0) {
+            putIntParts(o, offset,
+                        (short)(x >> 0),
+                        (short)(x >>> 16));
+        } else {
+            putIntParts(o, offset,
+                        (byte)(x >>> 0),
+                        (byte)(x >>> 8),
+                        (byte)(x >>> 16),
+                        (byte)(x >>> 24));
+        }
+    }
+    /** @see #putLongUnaligned(Object, long, long, boolean) */
+    public final void putIntUnaligned(Object o, long offset, int x, boolean bigEndian) {
+        putIntUnaligned(o, offset, convEndian(bigEndian, x));
+    }
+
+    /** @see #putLongUnaligned(Object, long, long) */
+    @HotSpotIntrinsicCandidate
+    public final void putShortUnaligned(Object o, long offset, short x) {
+        if ((offset & 1) == 0) {
+            putShort(o, offset, x);
+        } else {
+            putShortParts(o, offset,
+                          (byte)(x >>> 0),
+                          (byte)(x >>> 8));
+        }
+    }
+    /** @see #putLongUnaligned(Object, long, long, boolean) */
+    public final void putShortUnaligned(Object o, long offset, short x, boolean bigEndian) {
+        putShortUnaligned(o, offset, convEndian(bigEndian, x));
+    }
+
+    /** @see #putLongUnaligned(Object, long, long) */
+    @HotSpotIntrinsicCandidate
+    public final void putCharUnaligned(Object o, long offset, char x) {
+        putShortUnaligned(o, offset, (short)x);
+    }
+    /** @see #putLongUnaligned(Object, long, long, boolean) */
+    public final void putCharUnaligned(Object o, long offset, char x, boolean bigEndian) {
+        putCharUnaligned(o, offset, convEndian(bigEndian, x));
+    }
+
+    // JVM interface methods
+    private native boolean unalignedAccess0();
+    private native boolean isBigEndian0();
+
+    // BE is true iff the native endianness of this platform is big.
+    private static final boolean BE = theUnsafe.isBigEndian0();
+
+    // unalignedAccess is true iff this platform can perform unaligned accesses.
+    private static final boolean unalignedAccess = theUnsafe.unalignedAccess0();
+
+    private static int pickPos(int top, int pos) { return BE ? top - pos : pos; }
+
+    // These methods construct integers from bytes.  The byte ordering
+    // is the native endianness of this platform.
+    private static long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
+        return ((toUnsignedLong(i0) << pickPos(56, 0))
+              | (toUnsignedLong(i1) << pickPos(56, 8))
+              | (toUnsignedLong(i2) << pickPos(56, 16))
+              | (toUnsignedLong(i3) << pickPos(56, 24))
+              | (toUnsignedLong(i4) << pickPos(56, 32))
+              | (toUnsignedLong(i5) << pickPos(56, 40))
+              | (toUnsignedLong(i6) << pickPos(56, 48))
+              | (toUnsignedLong(i7) << pickPos(56, 56)));
+    }
+    private static long makeLong(short i0, short i1, short i2, short i3) {
+        return ((toUnsignedLong(i0) << pickPos(48, 0))
+              | (toUnsignedLong(i1) << pickPos(48, 16))
+              | (toUnsignedLong(i2) << pickPos(48, 32))
+              | (toUnsignedLong(i3) << pickPos(48, 48)));
+    }
+    private static long makeLong(int i0, int i1) {
+        return (toUnsignedLong(i0) << pickPos(32, 0))
+             | (toUnsignedLong(i1) << pickPos(32, 32));
+    }
+    private static int makeInt(short i0, short i1) {
+        return (toUnsignedInt(i0) << pickPos(16, 0))
+             | (toUnsignedInt(i1) << pickPos(16, 16));
+    }
+    private static int makeInt(byte i0, byte i1, byte i2, byte i3) {
+        return ((toUnsignedInt(i0) << pickPos(24, 0))
+              | (toUnsignedInt(i1) << pickPos(24, 8))
+              | (toUnsignedInt(i2) << pickPos(24, 16))
+              | (toUnsignedInt(i3) << pickPos(24, 24)));
+    }
+    private static short makeShort(byte i0, byte i1) {
+        return (short)((toUnsignedInt(i0) << pickPos(8, 0))
+                     | (toUnsignedInt(i1) << pickPos(8, 8)));
+    }
+
+    private static byte  pick(byte  le, byte  be) { return BE ? be : le; }
+    private static short pick(short le, short be) { return BE ? be : le; }
+    private static int   pick(int   le, int   be) { return BE ? be : le; }
+
+    // These methods write integers to memory from smaller parts
+    // provided by their caller.  The ordering in which these parts
+    // are written is the native endianness of this platform.
+    private void putLongParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
+        putByte(o, offset + 0, pick(i0, i7));
+        putByte(o, offset + 1, pick(i1, i6));
+        putByte(o, offset + 2, pick(i2, i5));
+        putByte(o, offset + 3, pick(i3, i4));
+        putByte(o, offset + 4, pick(i4, i3));
+        putByte(o, offset + 5, pick(i5, i2));
+        putByte(o, offset + 6, pick(i6, i1));
+        putByte(o, offset + 7, pick(i7, i0));
+    }
+    private void putLongParts(Object o, long offset, short i0, short i1, short i2, short i3) {
+        putShort(o, offset + 0, pick(i0, i3));
+        putShort(o, offset + 2, pick(i1, i2));
+        putShort(o, offset + 4, pick(i2, i1));
+        putShort(o, offset + 6, pick(i3, i0));
+    }
+    private void putLongParts(Object o, long offset, int i0, int i1) {
+        putInt(o, offset + 0, pick(i0, i1));
+        putInt(o, offset + 4, pick(i1, i0));
+    }
+    private void putIntParts(Object o, long offset, short i0, short i1) {
+        putShort(o, offset + 0, pick(i0, i1));
+        putShort(o, offset + 2, pick(i1, i0));
+    }
+    private void putIntParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3) {
+        putByte(o, offset + 0, pick(i0, i3));
+        putByte(o, offset + 1, pick(i1, i2));
+        putByte(o, offset + 2, pick(i2, i1));
+        putByte(o, offset + 3, pick(i3, i0));
+    }
+    private void putShortParts(Object o, long offset, byte i0, byte i1) {
+        putByte(o, offset + 0, pick(i0, i1));
+        putByte(o, offset + 1, pick(i1, i0));
+    }
+
+    // Zero-extend an integer
+    private static int toUnsignedInt(byte n)    { return n & 0xff; }
+    private static int toUnsignedInt(short n)   { return n & 0xffff; }
+    private static long toUnsignedLong(byte n)  { return n & 0xffl; }
+    private static long toUnsignedLong(short n) { return n & 0xffffl; }
+    private static long toUnsignedLong(int n)   { return n & 0xffffffffl; }
+
+    // Maybe byte-reverse an integer
+    private static char convEndian(boolean big, char n)   { return big == BE ? n : Character.reverseBytes(n); }
+    private static short convEndian(boolean big, short n) { return big == BE ? n : Short.reverseBytes(n)    ; }
+    private static int convEndian(boolean big, int n)     { return big == BE ? n : Integer.reverseBytes(n)  ; }
+    private static long convEndian(boolean big, long n)   { return big == BE ? n : Long.reverseBytes(n)     ; }
+}
--- a/jdk/src/java.base/share/classes/sun/invoke/anon/AnonymousClassLoader.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/invoke/anon/AnonymousClassLoader.java	Wed Jul 05 21:00:20 2017 +0200
@@ -78,7 +78,7 @@
         this.hostClass = hostClass;
     }
 
-    public static AnonymousClassLoader make(sun.misc.Unsafe unsafe, Class<?> hostClass) {
+    public static AnonymousClassLoader make(jdk.internal.misc.Unsafe unsafe, Class<?> hostClass) {
         if (unsafe == null)  throw new NullPointerException();
         return new AnonymousClassLoader(hostClass);
     }
@@ -189,13 +189,13 @@
     private static int fakeNameCounter = 99999;
 
     // ignore two warnings on this line:
-    private static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+    private static jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
     // preceding line requires that this class be on the boot class path
 
     private static final Method defineAnonymousClass;
     static {
         Method dac = null;
-        Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
+        Class<? extends jdk.internal.misc.Unsafe> unsafeClass = unsafe.getClass();
         try {
             dac = unsafeClass.getMethod("defineAnonymousClass",
                                         Class.class,
--- a/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,18 +27,19 @@
 
 public enum Wrapper {
     //        wrapperType    primitiveType  char            zero         emptyArray          format
-    BOOLEAN(  Boolean.class, boolean.class, 'Z',      (Boolean)false, new boolean[0], Format.unsigned( 1)),
+    BOOLEAN(  Boolean.class, boolean.class, 'Z',          Boolean.FALSE, new boolean[0], Format.unsigned( 1)),
     // These must be in the order defined for widening primitive conversions in JLS 5.1.2
-    BYTE   (     Byte.class,    byte.class, 'B',       (Byte)(byte)0, new    byte[0], Format.signed(   8)),
-    SHORT  (    Short.class,   short.class, 'S',     (Short)(short)0, new   short[0], Format.signed(  16)),
-    CHAR   (Character.class,    char.class, 'C',  (Character)(char)0, new    char[0], Format.unsigned(16)),
-    INT    (  Integer.class,     int.class, 'I', (Integer)/*(int)*/0, new     int[0], Format.signed(  32)),
-    LONG   (     Long.class,    long.class, 'J',       (Long)(long)0, new    long[0], Format.signed(  64)),
-    FLOAT  (    Float.class,   float.class, 'F',     (Float)(float)0, new   float[0], Format.floating(32)),
-    DOUBLE (   Double.class,  double.class, 'D',   (Double)(double)0, new  double[0], Format.floating(64)),
-    OBJECT (   Object.class,  Object.class, 'L',                null, new  Object[0], Format.other(    1)),
+    // Avoid boxing integral types here to defer initialization of internal caches
+    BYTE   (     Byte.class,    byte.class, 'B',      new Byte((byte)0), new    byte[0], Format.signed(   8)),
+    SHORT  (    Short.class,   short.class, 'S',    new Short((short)0), new   short[0], Format.signed(  16)),
+    CHAR   (Character.class,    char.class, 'C', new Character((char)0), new    char[0], Format.unsigned(16)),
+    INT    (  Integer.class,     int.class, 'I',         new Integer(0), new     int[0], Format.signed(  32)),
+    LONG   (     Long.class,    long.class, 'J',            new Long(0), new    long[0], Format.signed(  64)),
+    FLOAT  (    Float.class,   float.class, 'F',        (Float)(float)0, new   float[0], Format.floating(32)),
+    DOUBLE (   Double.class,  double.class, 'D',      (Double)(double)0, new  double[0], Format.floating(64)),
+    OBJECT (   Object.class,  Object.class, 'L',                   null, new  Object[0], Format.other(    1)),
     // VOID must be the last type, since it is "assignable" from any other type:
-    VOID   (     Void.class,    void.class, 'V',                null,           null, Format.other(    0)),
+    VOID   (     Void.class,    void.class, 'V',                   null,           null, Format.other(    0)),
     ;
 
     private final Class<?> wrapperType;
--- a/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java	Wed Jul 05 21:00:20 2017 +0200
@@ -36,7 +36,7 @@
  * ThreadGroup and supports the ability to erase ThreadLocals.
  */
 public final class InnocuousThread extends ManagedLocalsThread {
-    private static final Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
     private static final ThreadGroup INNOCUOUSTHREADGROUP;
     private static final AccessControlContext ACC;
     private static final long INHERITEDACCESSCONTROLCONTEXT;
@@ -92,7 +92,7 @@
             });
 
             // Find and use topmost ThreadGroup as parent of new group
-            UNSAFE = Unsafe.getUnsafe();
+            UNSAFE = jdk.internal.misc.Unsafe.getUnsafe();
             Class<?> tk = Thread.class;
             Class<?> gk = ThreadGroup.class;
 
--- a/jdk/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/misc/ManagedLocalsThread.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,7 +30,7 @@
  * locals erased on construction.
  */
 public class ManagedLocalsThread extends Thread {
-    private static final Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
     private static final long THREAD_LOCALS;
     private static final long INHERITABLE_THREAD_LOCALS;
 
@@ -77,7 +77,7 @@
     }
 
     static {
-        UNSAFE = Unsafe.getUnsafe();
+        UNSAFE = jdk.internal.misc.Unsafe.getUnsafe();
         Class<?> t = Thread.class;
         try {
             THREAD_LOCALS = UNSAFE.objectFieldOffset
--- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1036,355 +1036,8 @@
         throw new IllegalAccessError();
     }
 
-    /**
-     * @return Returns true if the native byte ordering of this
-     * platform is big-endian, false if it is little-endian.
-     */
-    public final boolean isBigEndian() { return BE; }
-
-    /**
-     * @return Returns true if this platform is capable of performing
-     * accesses at addresses which are not aligned for the type of the
-     * primitive type being accessed, false otherwise.
-     */
-    public final boolean unalignedAccess() { return unalignedAccess; }
-
-    /**
-     * Fetches a value at some byte offset into a given Java object.
-     * More specifically, fetches a value within the given object
-     * <code>o</code> at the given offset, or (if <code>o</code> is
-     * null) from the memory address whose numerical value is the
-     * given offset.  <p>
-     *
-     * The specification of this method is the same as {@link
-     * #getLong(Object, long)} except that the offset does not need to
-     * have been obtained from {@link #objectFieldOffset} on the
-     * {@link java.lang.reflect.Field} of some Java field.  The value
-     * in memory is raw data, and need not correspond to any Java
-     * variable.  Unless <code>o</code> is null, the value accessed
-     * must be entirely within the allocated object.  The endianness
-     * of the value in memory is the endianness of the native platform.
-     *
-     * <p> The read will be atomic with respect to the largest power
-     * of two that divides the GCD of the offset and the storage size.
-     * For example, getLongUnaligned will make atomic reads of 2-, 4-,
-     * or 8-byte storage units if the offset is zero mod 2, 4, or 8,
-     * respectively.  There are no other guarantees of atomicity.
-     * <p>
-     * 8-byte atomicity is only guaranteed on platforms on which
-     * support atomic accesses to longs.
-     *
-     * @param o Java heap object in which the value resides, if any, else
-     *        null
-     * @param offset The offset in bytes from the start of the object
-     * @return the value fetched from the indicated object
-     * @throws RuntimeException No defined exceptions are thrown, not even
-     *         {@link NullPointerException}
-     * @since 1.9
-     */
-    @HotSpotIntrinsicCandidate
-    public final long getLongUnaligned(Object o, long offset) {
-        if ((offset & 7) == 0) {
-            return getLong(o, offset);
-        } else if ((offset & 3) == 0) {
-            return makeLong(getInt(o, offset),
-                            getInt(o, offset + 4));
-        } else if ((offset & 1) == 0) {
-            return makeLong(getShort(o, offset),
-                            getShort(o, offset + 2),
-                            getShort(o, offset + 4),
-                            getShort(o, offset + 6));
-        } else {
-            return makeLong(getByte(o, offset),
-                            getByte(o, offset + 1),
-                            getByte(o, offset + 2),
-                            getByte(o, offset + 3),
-                            getByte(o, offset + 4),
-                            getByte(o, offset + 5),
-                            getByte(o, offset + 6),
-                            getByte(o, offset + 7));
-        }
-    }
-    /**
-     * As {@link #getLongUnaligned(Object, long)} but with an
-     * additional argument which specifies the endianness of the value
-     * as stored in memory.
-     *
-     * @param o Java heap object in which the variable resides
-     * @param offset The offset in bytes from the start of the object
-     * @param bigEndian The endianness of the value
-     * @return the value fetched from the indicated object
-     * @since 1.9
-     */
-    public final long getLongUnaligned(Object o, long offset, boolean bigEndian) {
-        return convEndian(bigEndian, getLongUnaligned(o, offset));
-    }
-
-    /** @see #getLongUnaligned(Object, long) */
-    @HotSpotIntrinsicCandidate
-    public final int getIntUnaligned(Object o, long offset) {
-        if ((offset & 3) == 0) {
-            return getInt(o, offset);
-        } else if ((offset & 1) == 0) {
-            return makeInt(getShort(o, offset),
-                           getShort(o, offset + 2));
-        } else {
-            return makeInt(getByte(o, offset),
-                           getByte(o, offset + 1),
-                           getByte(o, offset + 2),
-                           getByte(o, offset + 3));
-        }
-    }
-    /** @see #getLongUnaligned(Object, long, boolean) */
-    public final int getIntUnaligned(Object o, long offset, boolean bigEndian) {
-        return convEndian(bigEndian, getIntUnaligned(o, offset));
-    }
-
-    /** @see #getLongUnaligned(Object, long) */
-    @HotSpotIntrinsicCandidate
-    public final short getShortUnaligned(Object o, long offset) {
-        if ((offset & 1) == 0) {
-            return getShort(o, offset);
-        } else {
-            return makeShort(getByte(o, offset),
-                             getByte(o, offset + 1));
-        }
-    }
-    /** @see #getLongUnaligned(Object, long, boolean) */
-    public final short getShortUnaligned(Object o, long offset, boolean bigEndian) {
-        return convEndian(bigEndian, getShortUnaligned(o, offset));
-    }
-
-    /** @see #getLongUnaligned(Object, long) */
-    @HotSpotIntrinsicCandidate
-    public final char getCharUnaligned(Object o, long offset) {
-        return (char)getShortUnaligned(o, offset);
-    }
-
-    /** @see #getLongUnaligned(Object, long, boolean) */
-    public final char getCharUnaligned(Object o, long offset, boolean bigEndian) {
-        return convEndian(bigEndian, getCharUnaligned(o, offset));
-    }
-
-    /**
-     * Stores a value at some byte offset into a given Java object.
-     * <p>
-     * The specification of this method is the same as {@link
-     * #getLong(Object, long)} except that the offset does not need to
-     * have been obtained from {@link #objectFieldOffset} on the
-     * {@link java.lang.reflect.Field} of some Java field.  The value
-     * in memory is raw data, and need not correspond to any Java
-     * variable.  The endianness of the value in memory is the
-     * endianness of the native platform.
-     * <p>
-     * The write will be atomic with respect to the largest power of
-     * two that divides the GCD of the offset and the storage size.
-     * For example, putLongUnaligned will make atomic writes of 2-, 4-,
-     * or 8-byte storage units if the offset is zero mod 2, 4, or 8,
-     * respectively.  There are no other guarantees of atomicity.
-     * <p>
-     * 8-byte atomicity is only guaranteed on platforms on which
-     * support atomic accesses to longs.
-     *
-     * @param o Java heap object in which the value resides, if any, else
-     *        null
-     * @param offset The offset in bytes from the start of the object
-     * @param x the value to store
-     * @throws RuntimeException No defined exceptions are thrown, not even
-     *         {@link NullPointerException}
-     * @since 1.9
-     */
-    @HotSpotIntrinsicCandidate
-    public final void putLongUnaligned(Object o, long offset, long x) {
-        if ((offset & 7) == 0) {
-            putLong(o, offset, x);
-        } else if ((offset & 3) == 0) {
-            putLongParts(o, offset,
-                         (int)(x >> 0),
-                         (int)(x >>> 32));
-        } else if ((offset & 1) == 0) {
-            putLongParts(o, offset,
-                         (short)(x >>> 0),
-                         (short)(x >>> 16),
-                         (short)(x >>> 32),
-                         (short)(x >>> 48));
-        } else {
-            putLongParts(o, offset,
-                         (byte)(x >>> 0),
-                         (byte)(x >>> 8),
-                         (byte)(x >>> 16),
-                         (byte)(x >>> 24),
-                         (byte)(x >>> 32),
-                         (byte)(x >>> 40),
-                         (byte)(x >>> 48),
-                         (byte)(x >>> 56));
-        }
-    }
-
-    /**
-     * As {@link #putLongUnaligned(Object, long, long)} but with an additional
-     * argument which specifies the endianness of the value as stored in memory.
-     * @param o Java heap object in which the value resides
-     * @param offset The offset in bytes from the start of the object
-     * @param x the value to store
-     * @param bigEndian The endianness of the value
-     * @throws RuntimeException No defined exceptions are thrown, not even
-     *         {@link NullPointerException}
-     * @since 1.9
-     */
-    public final void putLongUnaligned(Object o, long offset, long x, boolean bigEndian) {
-        putLongUnaligned(o, offset, convEndian(bigEndian, x));
-    }
-
-    /** @see #putLongUnaligned(Object, long, long) */
-    @HotSpotIntrinsicCandidate
-    public final void putIntUnaligned(Object o, long offset, int x) {
-        if ((offset & 3) == 0) {
-            putInt(o, offset, x);
-        } else if ((offset & 1) == 0) {
-            putIntParts(o, offset,
-                        (short)(x >> 0),
-                        (short)(x >>> 16));
-        } else {
-            putIntParts(o, offset,
-                        (byte)(x >>> 0),
-                        (byte)(x >>> 8),
-                        (byte)(x >>> 16),
-                        (byte)(x >>> 24));
-        }
-    }
-    /** @see #putLongUnaligned(Object, long, long, boolean) */
-    public final void putIntUnaligned(Object o, long offset, int x, boolean bigEndian) {
-        putIntUnaligned(o, offset, convEndian(bigEndian, x));
-    }
-
-    /** @see #putLongUnaligned(Object, long, long) */
-    @HotSpotIntrinsicCandidate
-    public final void putShortUnaligned(Object o, long offset, short x) {
-        if ((offset & 1) == 0) {
-            putShort(o, offset, x);
-        } else {
-            putShortParts(o, offset,
-                          (byte)(x >>> 0),
-                          (byte)(x >>> 8));
-        }
-    }
-    /** @see #putLongUnaligned(Object, long, long, boolean) */
-    public final void putShortUnaligned(Object o, long offset, short x, boolean bigEndian) {
-        putShortUnaligned(o, offset, convEndian(bigEndian, x));
-    }
-
-    /** @see #putLongUnaligned(Object, long, long) */
-    @HotSpotIntrinsicCandidate
-    public final void putCharUnaligned(Object o, long offset, char x) {
-        putShortUnaligned(o, offset, (short)x);
-    }
-    /** @see #putLongUnaligned(Object, long, long, boolean) */
-    public final void putCharUnaligned(Object o, long offset, char x, boolean bigEndian) {
-        putCharUnaligned(o, offset, convEndian(bigEndian, x));
-    }
-
     // JVM interface methods
     private native boolean unalignedAccess0();
     private native boolean isBigEndian0();
 
-    // BE is true iff the native endianness of this platform is big.
-    private static final boolean BE = theUnsafe.isBigEndian0();
-
-    // unalignedAccess is true iff this platform can perform unaligned accesses.
-    private static final boolean unalignedAccess = theUnsafe.unalignedAccess0();
-
-    private static int pickPos(int top, int pos) { return BE ? top - pos : pos; }
-
-    // These methods construct integers from bytes.  The byte ordering
-    // is the native endianness of this platform.
-    private static long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
-        return ((toUnsignedLong(i0) << pickPos(56, 0))
-              | (toUnsignedLong(i1) << pickPos(56, 8))
-              | (toUnsignedLong(i2) << pickPos(56, 16))
-              | (toUnsignedLong(i3) << pickPos(56, 24))
-              | (toUnsignedLong(i4) << pickPos(56, 32))
-              | (toUnsignedLong(i5) << pickPos(56, 40))
-              | (toUnsignedLong(i6) << pickPos(56, 48))
-              | (toUnsignedLong(i7) << pickPos(56, 56)));
-    }
-    private static long makeLong(short i0, short i1, short i2, short i3) {
-        return ((toUnsignedLong(i0) << pickPos(48, 0))
-              | (toUnsignedLong(i1) << pickPos(48, 16))
-              | (toUnsignedLong(i2) << pickPos(48, 32))
-              | (toUnsignedLong(i3) << pickPos(48, 48)));
-    }
-    private static long makeLong(int i0, int i1) {
-        return (toUnsignedLong(i0) << pickPos(32, 0))
-             | (toUnsignedLong(i1) << pickPos(32, 32));
-    }
-    private static int makeInt(short i0, short i1) {
-        return (toUnsignedInt(i0) << pickPos(16, 0))
-             | (toUnsignedInt(i1) << pickPos(16, 16));
-    }
-    private static int makeInt(byte i0, byte i1, byte i2, byte i3) {
-        return ((toUnsignedInt(i0) << pickPos(24, 0))
-              | (toUnsignedInt(i1) << pickPos(24, 8))
-              | (toUnsignedInt(i2) << pickPos(24, 16))
-              | (toUnsignedInt(i3) << pickPos(24, 24)));
-    }
-    private static short makeShort(byte i0, byte i1) {
-        return (short)((toUnsignedInt(i0) << pickPos(8, 0))
-                     | (toUnsignedInt(i1) << pickPos(8, 8)));
-    }
-
-    private static byte  pick(byte  le, byte  be) { return BE ? be : le; }
-    private static short pick(short le, short be) { return BE ? be : le; }
-    private static int   pick(int   le, int   be) { return BE ? be : le; }
-
-    // These methods write integers to memory from smaller parts
-    // provided by their caller.  The ordering in which these parts
-    // are written is the native endianness of this platform.
-    private void putLongParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
-        putByte(o, offset + 0, pick(i0, i7));
-        putByte(o, offset + 1, pick(i1, i6));
-        putByte(o, offset + 2, pick(i2, i5));
-        putByte(o, offset + 3, pick(i3, i4));
-        putByte(o, offset + 4, pick(i4, i3));
-        putByte(o, offset + 5, pick(i5, i2));
-        putByte(o, offset + 6, pick(i6, i1));
-        putByte(o, offset + 7, pick(i7, i0));
-    }
-    private void putLongParts(Object o, long offset, short i0, short i1, short i2, short i3) {
-        putShort(o, offset + 0, pick(i0, i3));
-        putShort(o, offset + 2, pick(i1, i2));
-        putShort(o, offset + 4, pick(i2, i1));
-        putShort(o, offset + 6, pick(i3, i0));
-    }
-    private void putLongParts(Object o, long offset, int i0, int i1) {
-        putInt(o, offset + 0, pick(i0, i1));
-        putInt(o, offset + 4, pick(i1, i0));
-    }
-    private void putIntParts(Object o, long offset, short i0, short i1) {
-        putShort(o, offset + 0, pick(i0, i1));
-        putShort(o, offset + 2, pick(i1, i0));
-    }
-    private void putIntParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3) {
-        putByte(o, offset + 0, pick(i0, i3));
-        putByte(o, offset + 1, pick(i1, i2));
-        putByte(o, offset + 2, pick(i2, i1));
-        putByte(o, offset + 3, pick(i3, i0));
-    }
-    private void putShortParts(Object o, long offset, byte i0, byte i1) {
-        putByte(o, offset + 0, pick(i0, i1));
-        putByte(o, offset + 1, pick(i1, i0));
-    }
-
-    // Zero-extend an integer
-    private static int toUnsignedInt(byte n)    { return n & 0xff; }
-    private static int toUnsignedInt(short n)   { return n & 0xffff; }
-    private static long toUnsignedLong(byte n)  { return n & 0xffl; }
-    private static long toUnsignedLong(short n) { return n & 0xffffl; }
-    private static long toUnsignedLong(int n)   { return n & 0xffffffffl; }
-
-    // Maybe byte-reverse an integer
-    private static char convEndian(boolean big, char n)   { return big == BE ? n : Character.reverseBytes(n); }
-    private static short convEndian(boolean big, short n) { return big == BE ? n : Short.reverseBytes(n)    ; }
-    private static int convEndian(boolean big, int n)     { return big == BE ? n : Integer.reverseBytes(n)  ; }
-    private static long convEndian(boolean big, long n)   { return big == BE ? n : Long.reverseBytes(n)     ; }
 }
--- a/jdk/src/java.base/share/classes/sun/nio/ch/NativeObject.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/NativeObject.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,7 +29,7 @@
 package sun.nio.ch;                                     // Formerly in sun.misc
 
 import java.nio.ByteOrder;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 
 // ## In the fullness of time, this class will be eliminated
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java	Wed Jul 05 21:00:20 2017 +0200
@@ -35,7 +35,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.*;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.misc.Cleaner;
 import sun.security.action.GetPropertyAction;
 
--- a/jdk/src/java.base/share/classes/sun/nio/cs/ArrayDecoder.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/ArrayDecoder.java	Wed Jul 05 21:00:20 2017 +0200
@@ -32,4 +32,8 @@
 
 public interface ArrayDecoder {
     int decode(byte[] src, int off, int len, char[] dst);
+
+    default boolean isASCIICompatible() {
+        return false;
+    }
 }
--- a/jdk/src/java.base/share/classes/sun/nio/cs/ArrayEncoder.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/ArrayEncoder.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,10 +26,24 @@
 package sun.nio.cs;
 
 /*
- * FastPath char[]->byte[] encoder, REPLACE on malformed input or
+ * FastPath char[]/byte[] -> byte[] encoder, REPLACE on malformed input or
  * unmappable input.
  */
 
 public interface ArrayEncoder {
+
+    //  is only used by j.u.zip.ZipCoder for utf8
     int encode(char[] src, int off, int len, byte[] dst);
+
+    default int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
+        return -1;
+    }
+
+    default int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
+        return -1;
+    }
+
+    default boolean isASCIICompatible() {
+        return false;
+    }
 }
--- a/jdk/src/java.base/share/classes/sun/nio/cs/DoubleByte.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/DoubleByte.java	Wed Jul 05 21:00:20 2017 +0200
@@ -115,6 +115,7 @@
         final char[] b2cSB;
         final int b2Min;
         final int b2Max;
+        final boolean isASCIICompatible;
 
         // for SimpleEUC override
         protected CoderResult crMalformedOrUnderFlow(int b) {
@@ -132,16 +133,23 @@
 
         public Decoder(Charset cs, float avgcpb, float maxcpb,
                        char[][] b2c, char[] b2cSB,
-                       int b2Min, int b2Max) {
+                       int b2Min, int b2Max,
+                       boolean isASCIICompatible) {
             super(cs, avgcpb, maxcpb);
             this.b2c = b2c;
             this.b2cSB = b2cSB;
             this.b2Min = b2Min;
             this.b2Max = b2Max;
+            this.isASCIICompatible = isASCIICompatible;
+        }
+
+        public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
+                       boolean isASCIICompatible) {
+            this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
         }
 
         public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
-            this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max);
+            this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max, false);
         }
 
         protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
@@ -215,6 +223,7 @@
                 return decodeBufferLoop(src, dst);
         }
 
+        @Override
         public int decode(byte[] src, int sp, int len, char[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -230,12 +239,12 @@
                             if (b2c[b1] == B2C_UNMAPPABLE ||  // isNotLeadingByte
                                 b2c[b2] != B2C_UNMAPPABLE ||  // isLeadingByte
                                 decodeSingle(b2) != UNMAPPABLE_DECODING) {
-                                sp--;
+                               sp--;
                             }
                         }
                     }
                     if (c == UNMAPPABLE_DECODING) {
-                        c = repl;
+                         c = repl;
                     }
                 }
                 dst[dp++] = c;
@@ -243,6 +252,11 @@
             return dp;
         }
 
+        @Override
+        public boolean isASCIICompatible() {
+            return isASCIICompatible;
+        }
+
         public void implReset() {
             super.implReset();
         }
@@ -274,8 +288,14 @@
         private int  currentState;
 
         public Decoder_EBCDIC(Charset cs,
-                       char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
-            super(cs, b2c, b2cSB, b2Min, b2Max);
+                              char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
+                              boolean isASCIICompatible) {
+            super(cs, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
+        }
+
+        public Decoder_EBCDIC(Charset cs,
+                              char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
+            super(cs, b2c, b2cSB, b2Min, b2Max, false);
         }
 
         public void implReset() {
@@ -403,6 +423,7 @@
             }
         }
 
+        @Override
         public int decode(byte[] src, int sp, int len, char[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -451,8 +472,13 @@
             b2cSB_UNMAPPABLE = new char[0x100];
             Arrays.fill(b2cSB_UNMAPPABLE, UNMAPPABLE_DECODING);
         }
+        public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
+                                boolean isASCIICompatible) {
+            super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, isASCIICompatible);
+        }
+
         public Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
-            super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max);
+            super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max, false);
         }
     }
 
@@ -464,8 +490,9 @@
         private final int SS3 =  0x8F;
 
         public Decoder_EUC_SIM(Charset cs,
-                        char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
-            super(cs, b2c, b2cSB, b2Min, b2Max);
+                               char[][] b2c, char[] b2cSB, int b2Min, int b2Max,
+                               boolean isASCIICompatible) {
+            super(cs, b2c, b2cSB, b2Min, b2Max, isASCIICompatible);
         }
 
         // No support provided for G2/G3 for SimpleEUC
@@ -481,6 +508,7 @@
             return CoderResult.unmappableForLength(2);
         }
 
+        @Override
         public int decode(byte[] src, int sp, int len, char[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -515,17 +543,25 @@
         private final char[] c2b;
         private final char[] c2bIndex;
         protected Surrogate.Parser sgp;
+        final boolean isASCIICompatible;
 
         public Encoder(Charset cs, char[] c2b, char[] c2bIndex) {
+            this(cs, c2b, c2bIndex, false);
+        }
+
+        public Encoder(Charset cs, char[] c2b, char[] c2bIndex, boolean isASCIICompatible) {
             super(cs, 2.0f, 2.0f);
             this.c2b = c2b;
             this.c2bIndex = c2bIndex;
+            this.isASCIICompatible = isASCIICompatible;
         }
 
-        public Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex) {
+        public Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex,
+                       boolean isASCIICompatible) {
             super(cs, avg, max, repl);
             this.c2b = c2b;
             this.c2bIndex = c2bIndex;
+            this.isASCIICompatible = isASCIICompatible;
         }
 
         public boolean canEncode(char c) {
@@ -624,6 +660,7 @@
             repl = newReplacement;
         }
 
+        @Override
         public int encode(char[] src, int sp, int len, byte[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -647,11 +684,69 @@
                 } else {                          // SingleByte
                     dst[dp++] = (byte)bb;
                 }
+            }
+            return dp;
+        }
+
+        @Override
+        public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + len;
+            while (sp < sl) {
+                char c = (char)(src[sp++] & 0xff);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    // no surrogate pair in latin1 string
+                    dst[dp++] = repl[0];
+                    if (repl.length > 1) {
+                        dst[dp++] = repl[1];
+                    }
+                    continue;
+                } //else
+                if (bb > MAX_SINGLEBYTE) { // DoubleByte
+                    dst[dp++] = (byte)(bb >> 8);
+                    dst[dp++] = (byte)bb;
+                } else {                   // SingleByte
+                    dst[dp++] = (byte)bb;
+                }
 
             }
             return dp;
         }
 
+        @Override
+        public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + len;
+            while (sp < sl) {
+                char c = StringUTF16.getChar(src, sp++);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    if (Character.isHighSurrogate(c) && sp < sl &&
+                        Character.isLowSurrogate(StringUTF16.getChar(src, sp))) {
+                        sp++;
+                    }
+                    dst[dp++] = repl[0];
+                    if (repl.length > 1) {
+                        dst[dp++] = repl[1];
+                    }
+                    continue;
+                } //else
+                if (bb > MAX_SINGLEBYTE) { // DoubleByte
+                    dst[dp++] = (byte)(bb >> 8);
+                    dst[dp++] = (byte)bb;
+                } else {                   // SingleByte
+                    dst[dp++] = (byte)bb;
+                }
+            }
+            return dp;
+        }
+
+        @Override
+        public boolean isASCIICompatible() {
+            return isASCIICompatible;
+        }
+
         public int encodeChar(char ch) {
             return c2b[c2bIndex[ch >> 8] + (ch & 0xff)];
         }
@@ -741,9 +836,11 @@
     }
 
     public static class Encoder_DBCSONLY extends Encoder {
+
         public Encoder_DBCSONLY(Charset cs, byte[] repl,
-                         char[] c2b, char[] c2bIndex) {
-            super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex);
+                                char[] c2b, char[] c2bIndex,
+                                boolean isASCIICompatible) {
+            super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex, isASCIICompatible);
         }
 
         public int encodeChar(char ch) {
@@ -754,8 +851,6 @@
         }
     }
 
-
-
     public static class Encoder_EBCDIC extends Encoder {
         static final int SBCS = 0;
         static final int DBCS = 1;
@@ -764,8 +859,9 @@
 
         protected int  currentState = SBCS;
 
-        public Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex) {
-            super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex);
+        public Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex,
+                              boolean isASCIICompatible) {
+            super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex, isASCIICompatible);
         }
 
         protected void implReset() {
@@ -878,6 +974,7 @@
             }
         }
 
+        @Override
         public int encode(char[] src, int sp, int len, byte[] dst) {
             int dp = 0;
             int sl = sp + len;
@@ -917,12 +1014,88 @@
             }
             return dp;
         }
+
+        @Override
+        public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + len;
+            while (sp < sl) {
+                char c = (char)(src[sp++] & 0xff);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    // no surrogate pair in latin1 string
+                    dst[dp++] = repl[0];
+                    if (repl.length > 1)
+                        dst[dp++] = repl[1];
+                    continue;
+                } //else
+                if (bb > MAX_SINGLEBYTE) {           // DoubleByte
+                    if (currentState == SBCS) {
+                        currentState = DBCS;
+                        dst[dp++] = SO;
+                    }
+                    dst[dp++] = (byte)(bb >> 8);
+                    dst[dp++] = (byte)bb;
+                } else {                             // SingleByte
+                    if (currentState == DBCS) {
+                         currentState = SBCS;
+                         dst[dp++] = SI;
+                    }
+                    dst[dp++] = (byte)bb;
+                }
+            }
+            if (currentState == DBCS) {
+                 currentState = SBCS;
+                 dst[dp++] = SI;
+            }
+            return dp;
+        }
+
+        @Override
+        public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + len;
+            while (sp < sl) {
+                char c = StringUTF16.getChar(src, sp++);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    if (Character.isHighSurrogate(c) && sp < sl &&
+                        Character.isLowSurrogate(StringUTF16.getChar(src, sp))) {
+                        sp++;
+                    }
+                    dst[dp++] = repl[0];
+                    if (repl.length > 1)
+                        dst[dp++] = repl[1];
+                    continue;
+                } //else
+                if (bb > MAX_SINGLEBYTE) {           // DoubleByte
+                    if (currentState == SBCS) {
+                        currentState = DBCS;
+                        dst[dp++] = SO;
+                    }
+                    dst[dp++] = (byte)(bb >> 8);
+                    dst[dp++] = (byte)bb;
+                } else {                             // SingleByte
+                    if (currentState == DBCS) {
+                         currentState = SBCS;
+                         dst[dp++] = SI;
+                    }
+                    dst[dp++] = (byte)bb;
+                }
+            }
+            if (currentState == DBCS) {
+                 currentState = SBCS;
+                 dst[dp++] = SI;
+            }
+            return dp;
+        }
     }
 
     // EUC_SIMPLE
     public static class Encoder_EUC_SIM extends Encoder {
-        public Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex) {
-            super(cs, c2b, c2bIndex);
+        public Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex,
+                               boolean isASCIICompatible) {
+            super(cs, c2b, c2bIndex, isASCIICompatible);
         }
     }
 
--- a/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java	Wed Jul 05 21:00:20 2017 +0200
@@ -53,7 +53,7 @@
             // super(cs, 0.5f, 1.0f);
             // need to extends DoubleByte.Decoder so the
             // sun.io can use it. this implementation
-            super(cs, 0.5f, 1.0f, null, null, 0, 0);
+            super(cs, 0.5f, 1.0f, null, null, 0, 0, true);
             this.big5Dec = big5Dec;
             this.b2cBmp = b2cBmp;
             this.b2cSupp = b2cSupp;
@@ -239,7 +239,7 @@
                           char[][] c2bBmp,
                           char[][] c2bSupp)
         {
-            super(cs, null, null);
+            super(cs, null, null, true);
             this.big5Enc = big5Enc;
             this.c2bBmp = c2bBmp;
             this.c2bSupp = c2bSupp;
@@ -389,6 +389,33 @@
             return dp;
         }
 
+        public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + len;
+            int dl = dst.length;
+            while (sp < sl) {
+                char c = StringUTF16.getChar(src, sp++);
+                int bb = encodeChar(c);
+                if (bb == UNMAPPABLE_ENCODING) {
+                    if (!Character.isHighSurrogate(c) || sp == sl ||
+                        !Character.isLowSurrogate(StringUTF16.getChar(src,sp)) ||
+                        (bb = encodeSupp(Character.toCodePoint(c, StringUTF16.getChar(src, sp++))))
+                        == UNMAPPABLE_ENCODING) {
+                        dst[dp++] = repl[0];
+                        if (repl.length > 1)
+                            dst[dp++] = repl[1];
+                        continue;
+                    }
+                }
+                if (bb > MAX_SINGLEBYTE) { // DoubleByte
+                    dst[dp++] = (byte)(bb >> 8);
+                    dst[dp++] = (byte)bb;
+                } else {                   // SingleByte
+                    dst[dp++] = (byte)bb;
+                }
+            }
+            return dp;
+        }
 
         static char[] C2B_UNMAPPABLE = new char[0x100];
         static {
--- a/jdk/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java	Wed Jul 05 21:00:20 2017 +0200
@@ -132,6 +132,10 @@
                 dst[dp++] = (char)(src[sp++] & 0xff);
             return dp;
         }
+
+        public boolean isASCIICompatible() {
+            return true;
+        }
     }
 
     private static class Encoder extends CharsetEncoder
@@ -297,5 +301,9 @@
             }
             return dp;
         }
+
+        public boolean isASCIICompatible() {
+            return true;
+        }
     }
 }
--- a/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/SingleByte.java	Wed Jul 05 21:00:20 2017 +0200
@@ -49,10 +49,18 @@
     public static final class Decoder extends CharsetDecoder
                                       implements ArrayDecoder {
         private final char[] b2c;
+        private final boolean isASCIICompatible;
 
         public Decoder(Charset cs, char[] b2c) {
             super(cs, 1.0f, 1.0f);
             this.b2c = b2c;
+            this.isASCIICompatible = false;
+        }
+
+        public Decoder(Charset cs, char[] b2c, boolean isASCIICompatible) {
+            super(cs, 1.0f, 1.0f);
+            this.b2c = b2c;
+            this.isASCIICompatible = isASCIICompatible;
         }
 
         private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
@@ -116,6 +124,7 @@
             repl = newReplacement.charAt(0);
         }
 
+        @Override
         public int decode(byte[] src, int sp, int len, char[] dst) {
             if (len > dst.length)
                 len = dst.length;
@@ -129,6 +138,11 @@
             }
             return dp;
         }
+
+        @Override
+        public boolean isASCIICompatible() {
+            return isASCIICompatible;
+        }
     }
 
     public static final class Encoder extends CharsetEncoder
@@ -136,11 +150,13 @@
         private Surrogate.Parser sgp;
         private final char[] c2b;
         private final char[] c2bIndex;
+        private final boolean isASCIICompatible;
 
-        public Encoder(Charset cs, char[] c2b, char[] c2bIndex) {
+        public Encoder(Charset cs, char[] c2b, char[] c2bIndex, boolean isASCIICompatible) {
             super(cs, 1.0f, 1.0f);
             this.c2b = c2b;
             this.c2bIndex = c2bIndex;
+            this.isASCIICompatible = isASCIICompatible;
         }
 
         public boolean canEncode(char c) {
@@ -252,6 +268,51 @@
             }
             return dp;
         }
+
+        @Override
+        public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + Math.min(len, dst.length);
+            while (sp < sl) {
+                char c = (char)(src[sp++] & 0xff);
+                int b = encode(c);
+                if (b == UNMAPPABLE_ENCODING) {
+                    dst[dp++] = repl;
+                } else {
+                    dst[dp++] = (byte)b;
+                }
+            }
+            return dp;
+        }
+
+        @Override
+        public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
+            int dp = 0;
+            int sl = sp + Math.min(len, dst.length);
+            while (sp < sl) {
+                char c = StringUTF16.getChar(src, sp++);
+                int b = encode(c);
+                if (b != UNMAPPABLE_ENCODING) {
+                    dst[dp++] = (byte)b;
+                    continue;
+                }
+                if (Character.isHighSurrogate(c) && sp < sl &&
+                    Character.isLowSurrogate(StringUTF16.getChar(src, sp))) {
+                    if (len > dst.length) {
+                        sl++;
+                        len--;
+                    }
+                    sp++;
+                }
+                dst[dp++] = repl;
+            }
+            return dp;
+        }
+
+        @Override
+        public boolean isASCIICompatible() {
+            return isASCIICompatible;
+        }
     }
 
     // init the c2b and c2bIndex tables from b2c.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/StringUTF16.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.cs;
+
+import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
+import static sun.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE;
+
+class StringUTF16 {
+
+    public static char getChar(byte[] val, int index) {
+        return unsafe.getChar(val,
+                              ARRAY_BYTE_BASE_OFFSET + ARRAY_BYTE_INDEX_SCALE * index * 2L);
+    }
+
+    private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+}
--- a/jdk/src/java.base/share/classes/sun/nio/cs/US_ASCII.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/US_ASCII.java	Wed Jul 05 21:00:20 2017 +0200
@@ -146,6 +146,10 @@
             }
             return dp;
         }
+
+        public boolean isASCIICompatible() {
+            return true;
+        }
     }
 
     private static class Encoder extends CharsetEncoder
@@ -259,6 +263,10 @@
             }
             return dp;
         }
+
+        public boolean isASCIICompatible() {
+            return true;
+        }
     }
 
 }
--- a/jdk/src/java.base/share/classes/sun/nio/cs/UTF_8.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/UTF_8.java	Wed Jul 05 21:00:20 2017 +0200
@@ -549,6 +549,10 @@
             }
             return dp;
         }
+
+        public boolean isASCIICompatible() {
+            return true;
+        }
     }
 
     private static final class Encoder extends CharsetEncoder
@@ -742,5 +746,9 @@
             }
             return dp;
         }
+
+        public boolean isASCIICompatible() {
+            return true;
+        }
     }
 }
--- a/jdk/src/java.base/share/classes/sun/nio/fs/Cancellable.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/Cancellable.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,7 +26,7 @@
 package sun.nio.fs;
 
 import sun.misc.ManagedLocalsThread;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import java.util.concurrent.ExecutionException;
 
 /**
--- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,7 +25,7 @@
 
 package sun.nio.fs;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.misc.Cleaner;
 
 /**
--- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,7 +25,7 @@
 
 package sun.nio.fs;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Factory for native buffers.
--- a/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,7 +26,7 @@
 package sun.reflect;
 
 import java.lang.reflect.*;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /** Shared functionality for all accessor generators */
 
--- a/jdk/src/java.base/share/classes/sun/reflect/ClassDefiner.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/ClassDefiner.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /** Utility class which assists in calling Unsafe.defineClass() by
     creating a new class loader which delegates to the one needed in
--- a/jdk/src/java.base/share/classes/sun/reflect/FieldInfo.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/FieldInfo.java	Wed Jul 05 21:00:20 2017 +0200
@@ -38,7 +38,7 @@
     private String signature;
     private int    modifiers;
     // This is compatible with the old reflection implementation's
-    // "slot" value to allow sun.misc.Unsafe to work
+    // "slot" value to allow jdk.internal.misc.Unsafe to work
     private int    slot;
 
     // Not really necessary to provide a constructor since the VM
--- a/jdk/src/java.base/share/classes/sun/reflect/MagicAccessorImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/MagicAccessorImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -32,7 +32,7 @@
     fields and methods of other classes. It is used to hold the code
     for dynamically-generated FieldAccessorImpl and MethodAccessorImpl
     subclasses. (Use of the word "unsafe" was avoided in this class's
-    name to avoid confusion with {@link sun.misc.Unsafe}.) </P>
+    name to avoid confusion with {@link jdk.internal.misc.Unsafe}.) </P>
 
     <P> The bug fix for 4486457 also necessitated disabling
     verification for this class and all subclasses, as opposed to just
--- a/jdk/src/java.base/share/classes/sun/reflect/ReflectionFactory.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/ReflectionFactory.java	Wed Jul 05 21:00:20 2017 +0200
@@ -44,7 +44,7 @@
     subversion of both the language and the verifier. For this reason,
     they are all instance methods, and access to the constructor of
     this factory is guarded by a security check, in similar style to
-    {@link sun.misc.Unsafe}. </P>
+    {@link jdk.internal.misc.Unsafe}. </P>
 */
 
 public class ReflectionFactory {
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeFieldAccessorImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeFieldAccessorImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,9 +27,9 @@
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
-/** Base class for sun.misc.Unsafe-based FieldAccessors. The
+/** Base class for jdk.internal.misc.Unsafe-based FieldAccessors. The
     observation is that there are only nine types of fields from the
     standpoint of reflection code: the eight primitive types and
     Object. Using class Unsafe instead of generated bytecodes saves
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFieldAccessorImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFieldAccessorImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,10 +27,10 @@
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
- * Base class for sun.misc.Unsafe-based FieldAccessors for fields with
+ * Base class for jdk.internal.misc.Unsafe-based FieldAccessors for fields with
  * final or volatile qualifiers. These differ from unqualified
  * versions in that (1) they check for read-only status (2) they use
  * the volatile forms of Unsafe get/put methods. (When accessed via
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFieldAccessorImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFieldAccessorImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -28,9 +28,9 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
-/** Base class for sun.misc.Unsafe-based FieldAccessors for final or
+/** Base class for jdk.internal.misc.Unsafe-based FieldAccessors for final or
     static volatile fields.  */
 
 abstract class UnsafeQualifiedStaticFieldAccessorImpl
--- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFieldAccessorImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFieldAccessorImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -28,9 +28,9 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
-/** Base class for sun.misc.Unsafe-based FieldAccessors for static
+/** Base class for jdk.internal.misc.Unsafe-based FieldAccessors for static
     fields. The observation is that there are only nine types of
     fields from the standpoint of reflection code: the eight primitive
     types and Object. Using class Unsafe instead of generated
--- a/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/reflect/misc/ReflectUtil.java	Wed Jul 05 21:00:20 2017 +0200
@@ -337,7 +337,7 @@
 
     /**
      * Checks if {@code Class cls} is a VM-anonymous class
-     * as defined by {@link sun.misc.Unsafe#defineAnonymousClass}
+     * as defined by {@link jdk.internal.misc.Unsafe#defineAnonymousClass}
      * (not to be confused with a Java Language anonymous inner class).
      */
     public static boolean isVMAnonymousClass(Class<?> cls) {
--- a/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/provider/ByteArrayAccess.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,7 +30,7 @@
 
 import java.nio.ByteOrder;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Optimized methods for converting between byte[] and int[]/long[], both for
--- a/jdk/src/java.base/share/native/libjava/String.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libjava/String.c	Wed Jul 05 21:00:20 2017 +0200
@@ -31,3 +31,14 @@
 {
     return JVM_InternString(env, this);
 }
+
+JNIEXPORT jboolean JNICALL
+Java_java_lang_StringUTF16_isBigEndian(JNIEnv *env, jclass cls)
+{
+  unsigned int endianTest = 0xff000000;
+  if (((char*)(&endianTest))[0] != 0) {
+    return JNI_TRUE;
+  } else {
+    return JNI_FALSE;
+  }
+}
--- a/jdk/src/java.base/share/native/libjava/check_version.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libjava/check_version.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,10 +24,11 @@
  */
 
 #include "jni.h"
+#include "jni_util.h"
 #include "jvm.h"
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     jint vm_version = JVM_GetInterfaceVersion();
     if (vm_version != JVM_INTERFACE_VERSION) {
--- a/jdk/src/java.base/share/native/libjava/jio.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libjava/jio.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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 "jni.h"
 
+#ifndef STATIC_BUILD
 
 /* This is a temporary solution until we figure out how to let native
  * libraries use jio_* without linking with the VM.
@@ -63,3 +64,6 @@
 
     return len;
 }
+
+#endif
+
--- a/jdk/src/java.base/share/native/libjava/jni_util.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libjava/jni_util.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -389,6 +389,117 @@
 
 extern size_t getLastErrorString(char *buf, size_t len);
 extern int getErrorString(int err, char *buf, size_t len);
+
+#ifdef STATIC_BUILD
+/* Macros for handling declaration of static/dynamic
+ * JNI library Load/Unload functions
+ *
+ * Use DEF_JNI_On{Un}Load when you want a static and non-static entry points.
+ * Use DEF_STATIC_JNI_On{Un}Load when you only want a static one.
+ *
+ * LIBRARY_NAME must be set to the name of the library
+ */
+
+/* These three macros are needed to get proper concatenation of
+ * the LIBRARY_NAME
+ *
+ * NOTE: LIBRARY_NAME must be set for static builds.
+ */
+#define ADD_LIB_NAME3(name, lib) name ## lib
+#define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib)
+#define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME)
+
+#define DEF_JNI_OnLoad \
+ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)(JavaVM *vm, void *reserved); \
+  ADD_LIB_NAME(JNI_OnLoad_dynamic_)(vm, reserved); \
+  return JNI_VERSION_1_8; \
+} \
+jint JNICALL ADD_LIB_NAME(JNI_OnLoad_dynamic_)
+
+#define DEF_STATIC_JNI_OnLoad \
+JNIEXPORT jint JNICALL ADD_LIB_NAME(JNI_OnLoad_)(JavaVM *vm, void *reserved) { \
+    return JNI_VERSION_1_8; \
+}
+
+#define DEF_JNI_OnUnload \
+ADD_LIB_NAME(JNI_OnUnload_)(JavaVM *vm, void *reserved) \
+{ \
+  void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)(JavaVM *vm, void *reserved); \
+  ADD_LIB_NAME(JNI_OnUnload_dynamic_)(vm, reserved); \
+} \
+void JNICALL ADD_LIB_NAME(JNI_OnUnload_dynamic_)
+
+#define DEF_STATIC_JNI_OnUnload \
+ADD_LIB_NAME(JNI_OnUnload_)
+
+#else
+
+#define DEF_JNI_OnLoad JNI_OnLoad
+#define DEF_STATIC_JNI_OnLoad
+#define DEF_JNI_OnUnload JNI_OnUnload
+#define DEF_STATIC_JNI_OnUnload
+#endif
+
+#ifdef STATIC_BUILD
+/* Macros for handling declaration of static/dynamic
+ * Agent library Load/Attach/Unload functions
+ *
+ * Use DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload
+ *     when you want both static and non-static entry points.
+ * Use DEF_STATIC_Agent_OnLoad, DEF_STATIC_Agent_OnAttach or
+ *     DEF_STATIC_Agent_OnUnload when you only want a static one.
+ *
+ * LIBRARY_NAME must be set to the name of the library for static builds.
+ */
+
+#define DEF_Agent_OnLoad \
+ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \
+  return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \
+} \
+jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)
+
+#define DEF_STATIC_Agent_OnLoad \
+JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \
+    return JNI_FALSE; \
+}
+
+#define DEF_Agent_OnAttach \
+ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \
+{ \
+  jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \
+  return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \
+} \
+jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)
+
+#define DEF_STATIC_Agent_OnAttach \
+JNIEXPORT jint JNICALL ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) { \
+    return JNI_FALSE; \
+}
+
+#define DEF_Agent_OnUnload \
+ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \
+{ \
+  void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \
+  ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \
+} \
+void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)
+
+#define DEF_STATIC_Agent_OnUnload \
+ADD_LIB_NAME(Agent_OnUnload_)
+
+#else
+#define DEF_Agent_OnLoad Agent_OnLoad
+#define DEF_Agent_OnAttach Agent_OnAttach
+#define DEF_Agent_OnUnload Agent_OnUnload
+#define DEF_STATIC_Agent_OnLoad
+#define DEF_STATIC_Agent_OnAttach
+#define DEF_STATIC_Agent_OnUnload
+#endif
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
--- a/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libjimage/ImageNativeSubstrate.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -26,6 +26,7 @@
 #include <string.h>
 
 #include "jni.h"
+#include "jni_util.h"
 
 #include "endian.hpp"
 #include "imageDecompressor.hpp"
@@ -246,7 +247,7 @@
 }
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved) {
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     JNIEnv *env;
 
     if (vm->GetEnv((void**) &env, JNI_VERSION_1_2) != JNI_OK) {
@@ -646,6 +647,6 @@
     return module;
 }
 
-JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
+JNIEXPORT void JNICALL DEF_JNI_OnUnload(JavaVM *vm, void *reserved) {
     ImageDecompressor::image_decompressor_close();
 }
--- a/jdk/src/java.base/share/native/libjimage/imageFile.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libjimage/imageFile.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -118,7 +118,7 @@
     // Deflate the attribute stream into an array of attributes.
     u1 byte;
     // Repeat until end header is found.
-    while ((byte = *data)) {
+    while ((data != NULL) && (byte = *data)) {
         // Extract kind from header byte.
         u1 kind = attribute_kind(byte);
         assert(kind < ATTRIBUTE_COUNT && "invalid image location attribute");
@@ -191,7 +191,7 @@
 // Release module data resource.
 ImageModuleData::~ImageModuleData() {
     if (_data) {
-        delete _data;
+        delete[] _data;
     }
 }
 
@@ -274,7 +274,7 @@
 }
 
 ImageFileReaderTable::~ImageFileReaderTable() {
-    delete _table;
+    delete[] _table;
 }
 
 // Add a new image entry to the table.
@@ -414,7 +414,7 @@
     close();
     // Free up name.
     if (_name) {
-        delete _name;
+        delete[] _name;
         _name = NULL;
     }
 }
@@ -668,7 +668,7 @@
                         &strings);
         // If not memory mapped then release temporary buffer.
         if (!MemoryMapImage) {
-                delete compressed_data;
+                delete[] compressed_data;
         }
     } else {
         // Read bytes from offset beyond the image index.
--- a/jdk/src/java.base/share/native/libnet/net_util.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libnet/net_util.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
 }
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     JNIEnv *env;
     jclass iCls;
--- a/jdk/src/java.base/share/native/libnio/nio_util.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libnio/nio_util.c	Wed Jul 05 21:00:20 2017 +0200
@@ -28,7 +28,7 @@
 #include "jni_util.h"
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     JNIEnv *env;
 
--- a/jdk/src/java.base/share/native/libverify/check_code.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libverify/check_code.c	Wed Jul 05 21:00:20 2017 +0200
@@ -86,6 +86,7 @@
 #include <stdlib.h>
 
 #include "jni.h"
+#include "jni_util.h"
 #include "jvm.h"
 #include "classfile_constants.h"
 #include "opcodes.in_out"
@@ -481,6 +482,11 @@
 static void print_formatted_methodname(context_type *context, int index);
 #endif
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 void initialize_class_hash(context_type *context)
 {
     hash_table_type *class_hash = &(context->class_hash);
--- a/jdk/src/java.base/share/native/libzip/ZipFile.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/share/native/libzip/ZipFile.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,6 +55,12 @@
 static int OPEN_READ = java_util_zip_ZipFile_OPEN_READ;
 static int OPEN_DELETE = java_util_zip_ZipFile_OPEN_DELETE;
 
+
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 JNIEXPORT void JNICALL
 Java_java_util_zip_ZipFile_initIDs(JNIEnv *env, jclass cls)
 {
--- a/jdk/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java	Wed Jul 05 21:00:20 2017 +0200
@@ -31,7 +31,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.security.action.GetIntegerAction;
 import static sun.nio.ch.SolarisEventPort.*;
 
--- a/jdk/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java	Wed Jul 05 21:00:20 2017 +0200
@@ -28,7 +28,7 @@
 import java.nio.channels.spi.AsynchronousChannelProvider;
 import java.util.concurrent.RejectedExecutionException;
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Provides an AsynchronousChannelGroup implementation based on the Solaris 10
--- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisAclFileAttributeView.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,7 +29,7 @@
 import java.nio.file.attribute.*;
 import java.util.*;
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.UnixConstants.*;
 import static sun.nio.fs.SolarisConstants.*;
--- a/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/SolarisWatchService.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,7 +30,7 @@
 import java.security.PrivilegedAction;
 import java.util.*;
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.UnixConstants.*;
 
--- a/jdk/src/java.base/unix/native/libjava/jlong_md.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/unix/native/libjava/jlong_md.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,11 +65,19 @@
 #define jlong_zero_init  ((jlong) 0L)
 
 #ifdef _LP64
-#define jlong_to_ptr(a) ((void*)(a))
-#define ptr_to_jlong(a) ((jlong)(a))
+  #ifndef jlong_to_ptr
+    #define jlong_to_ptr(a) ((void*)(a))
+  #endif
+  #ifndef ptr_to_jlong
+    #define ptr_to_jlong(a) ((jlong)(a))
+  #endif
 #else
-#define jlong_to_ptr(a) ((void*)(int)(a))
-#define ptr_to_jlong(a) ((jlong)(int)(a))
+  #ifndef jlong_to_ptr
+    #define jlong_to_ptr(a) ((void*)(int)(a))
+  #endif
+  #ifndef ptr_to_jlong
+    #define ptr_to_jlong(a) ((jlong)(int)(a))
+  #endif
 #endif
 
 #define jint_to_jlong(a)        ((jlong)(a))
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/Iocp.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/Iocp.java	Wed Jul 05 21:00:20 2017 +0200
@@ -36,7 +36,7 @@
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.security.AccessController;
 import sun.security.action.GetPropertyAction;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Windows implementation of AsynchronousChannelGroup encapsulating an I/O
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/PendingIoCache.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/PendingIoCache.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 import java.nio.channels.*;
 import java.util.*;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Maintains a mapping of pending I/O requests (identified by the address of
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -33,7 +33,7 @@
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Windows implementation of AsynchronousServerSocketChannel using overlapped I/O.
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -34,7 +34,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Windows implementation of AsynchronousSocketChannel using overlapped I/O.
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Wed Jul 05 21:00:20 2017 +0200
@@ -28,7 +28,7 @@
 import java.nio.file.attribute.*;
 import java.util.concurrent.TimeUnit;
 import java.security.AccessController;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.security.action.GetPropertyAction;
 
 import static sun.nio.fs.WindowsNativeDispatcher.*;
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -33,7 +33,7 @@
 import java.io.*;
 import java.util.*;
 import java.security.AccessController;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.nio.ch.ThreadPool;
 import sun.security.util.SecurityConstants;
 
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsLinkSupport.java	Wed Jul 05 21:00:20 2017 +0200
@@ -30,7 +30,7 @@
 import java.io.IOError;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.WindowsNativeDispatcher.*;
 import static sun.nio.fs.WindowsConstants.*;
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Win32 and library calls.
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsSecurityDescriptor.java	Wed Jul 05 21:00:20 2017 +0200
@@ -29,7 +29,7 @@
 import java.nio.file.attribute.*;
 import java.util.*;
 import java.io.IOException;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.WindowsNativeDispatcher.*;
 import static sun.nio.fs.WindowsConstants.*;
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsUserDefinedFileAttributeView.java	Wed Jul 05 21:00:20 2017 +0200
@@ -31,7 +31,7 @@
 import java.nio.channels.FileChannel;
 import java.io.IOException;
 import java.util.*;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.WindowsNativeDispatcher.*;
 import static sun.nio.fs.WindowsConstants.*;
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java	Wed Jul 05 21:00:20 2017 +0200
@@ -36,7 +36,7 @@
 import java.util.Set;
 
 import com.sun.nio.file.ExtendedWatchEventModifier;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import static sun.nio.fs.WindowsNativeDispatcher.*;
 import static sun.nio.fs.WindowsConstants.*;
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m	Wed Jul 05 21:00:20 2017 +0200
@@ -740,7 +740,7 @@
     JNF_COCOA_EXIT(env)
 }
 
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     OSXAPP_SetJavaVM(vm);
 
     // We need to let Foundation know that this is a multithreaded application, if it isn't already.
--- a/jdk/src/java.desktop/macosx/native/libjawt/jawt.m	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libjawt/jawt.m	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,12 +24,18 @@
  */
 
 #import <jawt.h>
+#import "jni_util.h"
 
 #import <jawt_md.h>
 
 #import "awt_DrawingSurface.h"
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Get the AWT native structure.
  * This function returns JNI_FALSE if an error occurs.
  */
--- a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h	Wed Jul 05 21:00:20 2017 +0200
@@ -23,6 +23,12 @@
  * questions.
  */
 
+/*
+ * Must include this before JavaNativeFoundation.h to get jni.h from build
+ */
+#include "jni.h"
+#include "jni_util.h"
+
 #import <Cocoa/Cocoa.h>
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 
--- a/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m	Wed Jul 05 21:00:20 2017 +0200
@@ -33,6 +33,10 @@
 #import "QueuingApplicationDelegate.h"
 #import "AWTIconData.h"
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
 
 static BOOL sUsingDefaultNIB = YES;
 static NSString *SHARED_FRAMEWORK_BUNDLE = @"/System/Library/Frameworks/JavaVM.framework";
@@ -432,10 +436,10 @@
 @end
 
 
-void OSXAPP_SetApplicationDelegate(id <NSApplicationDelegate> delegate)
+void OSXAPP_SetApplicationDelegate(id <NSApplicationDelegate> newdelegate)
 {
 AWT_ASSERT_APPKIT_THREAD;
-    applicationDelegate = delegate;
+    applicationDelegate = newdelegate;
 
     if (NSApp != nil) {
         [NSApp setDelegate: applicationDelegate];
--- a/jdk/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,10 @@
  * questions.
  */
 
+// Must include this before JavaNativeFoundation.h to get jni.h from build
+#include "jni.h"
+#include "jni_util.h"
+
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 
 /*
@@ -30,6 +34,7 @@
  *    <rdar://4984599> AWT's JNI_OnLoad called multiple times
  *    Please remove when <rdar://5121166> has been resolved.
  */
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
+{
     return JNI_VERSION_1_4;
 }
--- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,7 +25,7 @@
 
 package sun.awt;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import javax.accessibility.AccessibleContext;
 import java.awt.*;
--- a/jdk/src/java.desktop/share/classes/sun/font/StrikeCache.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/StrikeCache.java	Wed Jul 05 21:00:20 2017 +0200
@@ -37,7 +37,7 @@
 import sun.java2d.pipe.BufferedContext;
 import sun.java2d.pipe.RenderQueue;
 import sun.java2d.pipe.hw.AccelGraphicsConfig;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
 
--- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/RenderBuffer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,7 +25,7 @@
 
 package sun.java2d.pipe;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 
 /**
--- a/jdk/src/java.desktop/share/classes/sun/swing/SwingAccessor.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/swing/SwingAccessor.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,7 +25,7 @@
 
 package sun.swing;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import java.awt.*;
 import javax.swing.*;
--- a/jdk/src/java.desktop/share/native/libfontmanager/sunFont.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libfontmanager/sunFont.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,10 @@
 static void *theNullScalerContext = NULL;
 extern void AccelGlyphCache_RemoveAllCellInfos(GlyphInfo *glyph);
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
 
 JNIEXPORT jlong JNICALL
 Java_sun_font_NullFontScaler_getNullScalerContext
--- a/jdk/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,7 +67,7 @@
 JavaVM *jvm;
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     jvm = vm;
     return JNI_VERSION_1_2;
--- a/jdk/src/java.desktop/share/native/libjsound/Platform.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libjsound/Platform.c	Wed Jul 05 21:00:20 2017 +0200
@@ -28,6 +28,10 @@
 // Platform.java includes
 #include "com_sun_media_sound_Platform.h"
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
 
 /*
  * Class:     com_sun_media_sound_Platform
--- a/jdk/src/java.desktop/share/native/libjsound/Utilities.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libjsound/Utilities.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
  */
 
 #include <jni.h>
+#include "jni_util.h"
 #include "SoundDefs.h"
 #include "Configure.h"          // put flags for debug msgs etc. here
 
--- a/jdk/src/java.desktop/share/native/liblcms/LCMS.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/native/liblcms/LCMS.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -134,7 +134,7 @@
     JNU_ThrowByName(env, "java/awt/color/CMMException", errMsg);
 }
 
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *jvm, void *reserved) {
     javaVM = jvm;
 
     cmsSetLogErrorHandler(errorHandler);
--- a/jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageUtils.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libmlib_image/mlib_ImageUtils.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,14 @@
 
 #include "mlib_image.h"
 
+#include <jni.h>
+#include "jni_util.h"
+
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 /***************************************************************/
 typedef union {
   mlib_d64 db;
--- a/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
 #include <sizecalc.h>
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM * vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM * vm, void *reserved)
 {
     return JNI_VERSION_1_2;
 }
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDConstants.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDConstants.java	Wed Jul 05 21:00:20 2017 +0200
@@ -31,7 +31,7 @@
 
 import java.util.Arrays;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Motif DnD protocol global constants and convenience routines.
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDragSourceProtocol.java	Wed Jul 05 21:00:20 2017 +0200
@@ -33,7 +33,7 @@
 
 import java.util.Map;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * XDragSourceProtocol implementation for Motif DnD protocol.
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/MotifDnDDropTargetProtocol.java	Wed Jul 05 21:00:20 2017 +0200
@@ -33,7 +33,7 @@
 
 import java.io.IOException;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * XDropTargetProtocol implementation for Motif DnD protocol.
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/Native.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,7 +25,7 @@
 
 package sun.awt.X11;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import java.util.Vector;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/UnsafeXDisposerRecord.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/UnsafeXDisposerRecord.java	Wed Jul 05 21:00:20 2017 +0200
@@ -24,7 +24,7 @@
  */
 package sun.awt.X11;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.util.logging.PlatformLogger;
 
 class UnsafeXDisposerRecord implements sun.java2d.DisposerRecord {
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/WindowPropertyGetter.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/WindowPropertyGetter.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,7 +26,7 @@
 package sun.awt.X11;
 
 import java.util.*;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 public class WindowPropertyGetter {
     private static Unsafe unsafe = XlibWrapper.unsafe;
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAtom.java	Wed Jul 05 21:00:20 2017 +0200
@@ -55,7 +55,7 @@
  * @since       1.5
  */
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import java.util.HashMap;
 
 public final class XAtom {
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java	Wed Jul 05 21:00:20 2017 +0200
@@ -35,7 +35,7 @@
 
 import sun.util.logging.PlatformLogger;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * XDragSourceProtocol implementation for XDnD protocol.
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDnDDropTargetProtocol.java	Wed Jul 05 21:00:20 2017 +0200
@@ -35,7 +35,7 @@
 
 import sun.util.logging.PlatformLogger;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * XDropTargetProtocol implementation for XDnD protocol.
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDropTargetContextPeer.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDropTargetContextPeer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -41,7 +41,7 @@
 import sun.awt.dnd.SunDropTargetContextPeer;
 import sun.awt.dnd.SunDropTargetEvent;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * The XDropTargetContextPeer is the class responsible for handling
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedHelper.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedHelper.java	Wed Jul 05 21:00:20 2017 +0200
@@ -25,7 +25,7 @@
 
 package sun.awt.X11;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import sun.util.logging.PlatformLogger;
 
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeysym.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeysym.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 package sun.awt.X11;
 import java.util.Hashtable;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 import sun.util.logging.PlatformLogger;
 
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XQueryTree.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XQueryTree.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 package sun.awt.X11;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 public class XQueryTree {
         private static Unsafe unsafe = XlibWrapper.unsafe;
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTranslateCoordinates.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTranslateCoordinates.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 package sun.awt.X11;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 public class XTranslateCoordinates {
         private static Unsafe unsafe = XlibWrapper.unsafe;
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XWM.java	Wed Jul 05 21:00:20 2017 +0200
@@ -31,7 +31,7 @@
 package sun.awt.X11;
 
 import sun.awt.IconInfo;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import java.awt.Insets;
 import java.awt.Frame;
 import java.awt.Rectangle;
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XlibWrapper.java	Wed Jul 05 21:00:20 2017 +0200
@@ -27,7 +27,7 @@
 
 import java.security.AccessController;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 import sun.security.action.GetPropertyAction;
 
 final class XlibWrapper {
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/keysym2ucs.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/keysym2ucs.h	Wed Jul 05 21:00:20 2017 +0200
@@ -65,7 +65,7 @@
 tojava
 tojava package sun.awt.X11;
 tojava import java.util.Hashtable;
-tojava import sun.misc.Unsafe;
+tojava import jdk.internal.misc.Unsafe;
 tojava
 tojava import sun.util.logging.PlatformLogger;
 tojava
--- a/jdk/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -178,7 +178,7 @@
 }
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     return AWT_OnLoad(vm, reserved);
 }
--- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/HeadlessToolkit.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libawt_headless/awt/HeadlessToolkit.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,14 +31,17 @@
 extern JavaVM *jvm;
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     jvm = vm;
     return JNI_VERSION_1_2;
 }
 
+#ifndef STATIC_BUILD
+// The same function exists in libawt.a::awt_LoadLibrary.c
 JNIEXPORT jboolean JNICALL AWTIsHeadless() {
     return JNI_TRUE;
 }
+#endif
 
 #endif
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c	Wed Jul 05 21:00:20 2017 +0200
@@ -151,7 +151,7 @@
 
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     jvm = vm;
     return JNI_VERSION_1_2;
--- a/jdk/src/java.desktop/unix/native/libjawt/jawt.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libjawt/jawt.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,16 @@
  */
 
 #include <jawt.h>
+#include "jni_util.h"
 
 #include "awt_DrawingSurface.h"
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Get the AWT native structure.  This function returns JNI_FALSE if
  * an error occurs.
  */
--- a/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,11 @@
 static int alsa_enumerate_pcm_subdevices = FALSE; // default: no
 static int alsa_enumerate_midi_subdevices = FALSE; // default: no
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 void initAlsaSupport() {
     char* enumerate;
     if (!alsa_inited) {
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
 JavaVM *jvm = NULL;
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *vm, void *reserved)
+DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     TRY;
 
--- a/jdk/src/java.desktop/windows/native/libjawt/jawt.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.desktop/windows/native/libjawt/jawt.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,17 @@
 
 #define _JNI_IMPLEMENTATION_
 #include <jawt.h>
+#include "jni_util.h"
 
 #include "awt.h"
 #include "awt_DrawingSurface.h"
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Get the AWT native structure.  This function returns JNI_FALSE if
  * an error occurs.
  */
--- a/jdk/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,11 @@
  */
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Class:     sun_instrument_InstrumentationImpl
  * Method:    isModifiableClass0
  * Signature: (Ljava/lang/Class;)Z
--- a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@
  *  to create boot class path segments to append to the boot class path.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) {
+DEF_Agent_OnLoad(JavaVM *vm, char *tail, void * reserved) {
     JPLISInitializationError initerror  = JPLIS_INIT_ERROR_NONE;
     jint                     result     = JNI_OK;
     JPLISAgent *             agent      = NULL;
@@ -290,7 +290,7 @@
  *  the JPLIS library.
  */
 JNIEXPORT jint JNICALL
-Agent_OnAttach(JavaVM* vm, char *args, void * reserved) {
+DEF_Agent_OnAttach(JavaVM* vm, char *args, void * reserved) {
     JPLISInitializationError initerror  = JPLIS_INIT_ERROR_NONE;
     jint                     result     = JNI_OK;
     JPLISAgent *             agent      = NULL;
@@ -435,7 +435,7 @@
 
 
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm) {
+DEF_Agent_OnUnload(JavaVM *vm) {
 }
 
 
--- a/jdk/src/java.instrument/share/native/libinstrument/JarFacade.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.instrument/share/native/libinstrument/JarFacade.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,10 @@
  * questions.
  */
 
+#ifdef STATIC_BUILD
+#define getAttribute JarGetAttribute
+#endif
+
 typedef struct _jarAttribute {
     char* name;
     char* value;
--- a/jdk/src/java.instrument/share/native/libinstrument/Utilities.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.instrument/share/native/libinstrument/Utilities.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,6 +32,13 @@
 
 #include    <jni.h>
 #include    <jvmti.h>
+#include    "jni_util.h"
+
+#ifdef STATIC_BUILD
+#define allocate instAllocate
+#define deallocate instDeallocate
+#endif
+
 
 #ifdef __cplusplus
 extern "C" {
--- a/jdk/src/java.management/share/classes/sun/management/BaseOperatingSystemImpl.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.management/share/classes/sun/management/BaseOperatingSystemImpl.java	Wed Jul 05 21:00:20 2017 +0200
@@ -28,7 +28,7 @@
 import java.lang.management.OperatingSystemMXBean;
 import java.lang.management.ManagementFactory;
 import javax.management.ObjectName;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * Implementation class for the operating system.
--- a/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java	Wed Jul 05 21:00:20 2017 +0200
@@ -51,7 +51,7 @@
     static {
         // make sure that the management lib is loaded within
         // java.lang.management.ManagementFactory
-        sun.misc.Unsafe.getUnsafe().ensureClassInitialized(ManagementFactory.class);
+        jdk.internal.misc.Unsafe.getUnsafe().ensureClassInitialized(ManagementFactory.class);
     }
 
     private static final VMManagement jvm = new VMManagementImpl();
--- a/jdk/src/java.management/share/native/libmanagement/management.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.management/share/native/libmanagement/management.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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 @@
 
 #include <stdio.h>
 #include <jni.h>
+#include "jni_util.h"
 #include "jvm.h"
 #include "management.h"
 
@@ -35,7 +36,7 @@
 jint jmm_version = 0;
 
 JNIEXPORT jint JNICALL
-   JNI_OnLoad(JavaVM *vm, void *reserved) {
+   DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     JNIEnv* env;
 
     jvm = vm;
--- a/jdk/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,6 +64,11 @@
 #include "jlong.h"
 #include "jvm.h"
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 
 // Throw an OutOfMemoryError with the given message.
 static void throwOutOfMemoryError(JNIEnv *env, const char *msg)
--- a/jdk/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,11 @@
 #include <utime.h>
 #include "jni_util.h"
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 JNIEXPORT jint JNICALL
 Java_java_util_prefs_FileSystemPreferences_chmod(JNIEnv *env,
                        jclass thisclass, jstring java_fname, jint permission) {
--- a/jdk/src/java.prefs/windows/native/libprefs/WindowsPreferences.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.prefs/windows/native/libprefs/WindowsPreferences.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,12 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
     JNIEXPORT jintArray JNICALL Java_java_util_prefs_WindowsPreferences_WindowsRegOpenKey
                (JNIEnv* env, jclass this_class, jint hKey, jbyteArray lpSubKey, jint securityMask) {
         HKEY handle;
--- a/jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
 #import <string.h>
 #import <time.h>
 
+#include "jni_util.h"
+
 /*
  * Based largely on klist.c,
  *
@@ -92,7 +94,7 @@
  * Class:     sun_security_krb5_KrbCreds
  * Method:    JNI_OnLoad
  */
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *jvm, void *reserved)
 {
     JNIEnv *env;
 
@@ -191,7 +193,7 @@
  * Class:     sun_security_jgss_KrbCreds
  * Method:    JNI_OnUnload
  */
-JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved)
+JNIEXPORT void JNICALL DEF_JNI_OnUnload(JavaVM *jvm, void *reserved)
 {
     JNIEnv *env;
 
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KerberosSecrets.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KerberosSecrets.java	Wed Jul 05 21:00:20 2017 +0200
@@ -26,7 +26,7 @@
 package sun.security.krb5;
 
 import javax.security.auth.kerberos.KeyTab;
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 public class KerberosSecrets {
     private static final Unsafe unsafe = Unsafe.getUnsafe();
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java	Wed Jul 05 21:00:20 2017 +0200
@@ -187,10 +187,10 @@
     }
 
     private static final long NAME_STRINGS_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
+    private static final jdk.internal.misc.Unsafe UNSAFE;
     static {
         try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
             NAME_STRINGS_OFFSET = unsafe.objectFieldOffset(
                     PrincipalName.class.getDeclaredField("nameStrings"));
             UNSAFE = unsafe;
--- a/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 #include "NativeFunc.h"
 #include "jlong.h"
 #include <jni.h>
+#include "jni_util.h"
 
 const int JAVA_DUPLICATE_TOKEN_CODE = 19; /* DUPLICATE_TOKEN */
 const int JAVA_OLD_TOKEN_CODE = 20; /* OLD_TOKEN */
@@ -94,7 +95,7 @@
 int JGSS_DEBUG;
 
 JNIEXPORT jint JNICALL
-JNI_OnLoad(JavaVM *jvm, void *reserved) {
+DEF_JNI_OnLoad(JavaVM *jvm, void *reserved) {
   JNIEnv *env;
   jclass cls;
 
@@ -363,7 +364,7 @@
 }
 
 JNIEXPORT void JNICALL
-JNI_OnUnload(JavaVM *jvm, void *reserved) {
+DEF_JNI_OnUnload(JavaVM *jvm, void *reserved) {
   JNIEnv *env;
 
   if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) {
--- a/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.security.jgss/share/native/libj2gss/NativeUtil.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,9 +54,6 @@
   extern jstring getMinorMessage(JNIEnv *, jobject, OM_uint32);
   extern int sameMech(gss_OID, gss_OID);
 
-  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *, void *);
-  JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *, void *);
-
   extern int JGSS_DEBUG;
 
   extern jclass CLS_Object;
--- a/jdk/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,7 @@
 #include <lmcons.h>
 #include <lmapibuf.h>
 #include <jni.h>
+#include "jni_util.h"
 #include <winsock.h>
 
 #undef LSA_SUCCESS
@@ -107,7 +108,7 @@
  * Method:    JNI_OnLoad
  */
 
-JNIEXPORT jint JNICALL JNI_OnLoad(
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(
         JavaVM  *jvm,
         void    *reserved) {
 
@@ -329,7 +330,7 @@
  * Method:    JNI_OnUnload
  */
 
-JNIEXPORT void JNICALL JNI_OnUnload(
+JNIEXPORT void JNICALL DEF_JNI_OnUnload(
         JavaVM  *jvm,
         void    *reserved) {
 
--- a/jdk/src/java.smartcardio/share/native/libj2pcsc/pcsc.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/java.smartcardio/share/native/libj2pcsc/pcsc.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,6 +55,8 @@
 
 #include "pcsc_md.h"
 
+#include "jni_util.h"
+
 #define MAX_STACK_BUFFER_SIZE 8192
 
 // make the buffers larger than what should be necessary, just in case
@@ -101,7 +103,7 @@
     }
 }
 
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     return JNI_VERSION_1_4;
 }
 
--- a/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,11 @@
 } while(0)
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Defines a callback that is invoked for each process
  */
 typedef void (*ProcessCallback)(const pid_t pid, void* user_data);
--- a/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,11 @@
 } while(0)
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Class:     sun_tools_attach_VirtualMachineImpl
  * Method:    socket
  * Signature: ()I
--- a/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,11 @@
 } while(0)
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Class:     sun_tools_attach_VirtualMachineImpl
  * Method:    open
  * Signature: (Ljava/lang/String;)I
--- a/jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,10 @@
 #define ERR_OPEN_JVM_FAIL           200
 #define ERR_GET_ENQUEUE_FUNC_FAIL   201
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
 
 /*
  * Code copied to target process
--- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template	Wed Jul 05 21:00:20 2017 +0200
@@ -51,12 +51,12 @@
 
     public CharsetDecoder newDecoder() {
         initb2c();
-        return new  DoubleByte.Decoder(this, b2c, b2cSB, 0x40, 0xfe);
+        return new  DoubleByte.Decoder(this, b2c, b2cSB, 0x40, 0xfe, true);
     }
 
     public CharsetEncoder newEncoder() {
         initc2b();
-        return new DoubleByte.Encoder(this, c2b, c2bIndex);
+        return new DoubleByte.Encoder(this, c2b, c2bIndex, true);
     }
 
     static char[][] b2c;
--- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java	Wed Jul 05 21:00:20 2017 +0200
@@ -62,7 +62,7 @@
     protected static class Encoder extends DoubleByte.Encoder_DBCSONLY {
         public Encoder(Charset cs) {
             super(cs, new byte[] {(byte)0xfe, (byte)0xfe},
-                  IBM933.c2b, IBM933.c2bIndex);
+                  IBM933.c2b, IBM933.c2bIndex, false);
         }
 
         public int encodeChar(char ch) {
--- a/jdk/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
  */
 
 #include <jni.h>
+#include "jni_util.h"
 #include "impl/ecc_impl.h"
 
 #define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
@@ -36,6 +37,11 @@
 extern "C" {
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Throws an arbitrary Java exception.
  */
 void ThrowException(JNIEnv *env, const char *exceptionName)
--- a/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 //
 
 #include <jni.h>
+#include "jni_util.h"
 #include <stdlib.h>
 #include <string.h>
 #include <windows.h>
@@ -51,6 +52,11 @@
 extern "C" {
 
 /*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+/*
  * Throws an arbitrary Java exception.
  * The exception message is a Windows system error message.
  */
--- a/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_general.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.crypto.pkcs11/share/native/libj2pkcs11/p11_general.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  */
 
 /* Copyright  (c) 2002 Graz University of Technology. All rights reserved.
@@ -73,7 +73,7 @@
 
 JavaVM* jvm = NULL;
 
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     jvm = vm;
     return JNI_VERSION_1_4;
 }
--- a/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c	Wed Jul 05 21:00:20 2017 +0200
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <strings.h>
 #include <jni.h>
+#include "jni_util.h"
 #include <libsoftcrypto.h>
 #include "nativeCrypto.h"
 #include "nativeFunc.h"
@@ -59,7 +60,7 @@
   (*env)->DeleteLocalRef(env, jExClass);
 }
 
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     return JNI_VERSION_1_4;
 }
 
--- a/jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine/AppleScriptEngine.m	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine/AppleScriptEngine.m	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,10 @@
 #import "apple_applescript_AppleScriptEngine.h"
 #import "apple_applescript_AppleScriptEngineFactory.h"
 
+// Must include this before JavaNativeFoundation.h to get jni.h from build
+#include "jni.h"
+#include "jni_util.h"
+
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 
 #import "NS_Java_ConversionUtils.h"
@@ -33,6 +37,10 @@
 
 //#define DEBUG 1
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
 
 /*
  * Class:     apple_applescript_AppleScriptEngineFactory
--- a/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,21 @@
  * questions.
  */
 
+/*
+ * Must include this before JavaNativeFoundation.h to get jni.h from build
+ */
+#include "jni.h"
+#include "jni_util.h"
+
 #import "com_apple_concurrent_LibDispatchNative.h"
 
 #import <dispatch/dispatch.h>
 #import <JavaNativeFoundation/JavaNativeFoundation.h>
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
 
 /*
  * Class:     com_apple_concurrent_LibDispatchNative
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -194,7 +194,7 @@
  *   Returning JNI_ERR will cause the java_g VM to core dump, be careful.
  */
 JNIEXPORT jint JNICALL
-Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
+DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
 {
     jvmtiError error;
     jvmtiCapabilities needed_capabilities;
@@ -380,7 +380,7 @@
 }
 
 JNIEXPORT void JNICALL
-Agent_OnUnload(JavaVM *vm)
+DEF_Agent_OnUnload(JavaVM *vm)
 {
 
     gdata->isLoaded = JNI_FALSE;
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,4 @@
 void debugInit_exit(jvmtiError, const char *);
 void forceExit(int);
 
-JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *, char *, void *);
-JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *);
-
 #endif
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/transport.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/transport.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -101,9 +101,10 @@
 static void *
 loadTransportLibrary(const char *libdir, const char *name)
 {
+    char buf[MAXPATHLEN*2+100];
+#ifndef STATIC_BUILD
     void *handle;
     char libname[MAXPATHLEN+2];
-    char buf[MAXPATHLEN*2+100];
     const char *plibdir;
 
     /* Convert libdir from UTF-8 to platform encoding */
@@ -125,6 +126,9 @@
     /* dlopen (unix) / LoadLibrary (windows) the transport library */
     handle = dbgsysLoadLibrary(libname, buf, sizeof(buf));
     return handle;
+#else
+    return (dbgsysLoadLibrary(NULL, buf, sizeof(buf)));
+#endif
 }
 
 /*
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/util.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -278,18 +278,6 @@
 #define MOD_SYNTHETIC    0xf0000000  /* not in source code */
 
 /*
- * jlong conversion macros
- */
-#define jlong_zero       ((jlong) 0)
-#define jlong_one        ((jlong) 1)
-
-#define jlong_to_ptr(a)  ((void*)(intptr_t)(a))
-#define ptr_to_jlong(a)  ((jlong)(intptr_t)(a))
-#define jint_to_jlong(a) ((jlong)(a))
-#define jlong_to_jint(a) ((jint)(a))
-
-
-/*
  * util funcs
  */
 void util_initialize(JNIEnv *env);
--- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/vm_interface.h	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/vm_interface.h	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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 @@
 #include <jni.h>
 #include <jvm.h>
 #include <jvmti.h>
+#include "jni_util.h"
 
 #include "log_messages.h"
 
--- a/jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.c	Wed Jul 05 21:00:20 2017 +0200
@@ -25,6 +25,7 @@
 
 #include <stdio.h>
 #include <jni.h>
+#include "jni_util.h"
 #include "jvm.h"
 #include "management_ext.h"
 
@@ -35,7 +36,7 @@
 jint jmm_version = 0;
 
 JNIEXPORT jint JNICALL
-   JNI_OnLoad(JavaVM *vm, void *reserved) {
+   DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
     JNIEnv* env;
 
     jvm = vm;
--- a/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.pack200/share/native/common-unpack/utils.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,6 +77,8 @@
 
 
 #ifndef PRODUCT
+#ifndef STATIC_BUILD
+// use the definition in libjvm when building statically
 void breakpoint() { }  // hook for debugger
 int assert_failed(const char* p) {
   char message[1<<12];
@@ -87,6 +89,7 @@
   return 0;
 }
 #endif
+#endif
 
 void unpack_abort(const char* msg, unpacker* u) {
   if (msg == null)  msg = "corrupt pack file or internal error";
--- a/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.pack200/share/native/libunpack/jni.cpp	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -95,6 +95,11 @@
     } while (JNI_FALSE)
 #endif
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 static jlong read_input_via_jni(unpacker* self,
                                 void* buf, jlong minlen, jlong maxlen);
 
--- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
 static const char* nativeSctpLib = "libsctp.so.1";
 static jboolean funcsLoaded = JNI_FALSE;
 
-JNIEXPORT jint JNICALL JNI_OnLoad
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad
   (JavaVM *vm, void *reserved) {
     return JNI_VERSION_1_2;
 }
--- a/jdk/src/jdk.security.auth/unix/native/libjaas/Unix.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.security.auth/unix/native/libjaas/Unix.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 #endif
 
 #include <jni.h>
+#include "jni_util.h"
 #include "com_sun_security_auth_module_UnixSystem.h"
 #include <stdio.h>
 #include <pwd.h>
@@ -36,6 +37,11 @@
 #include <stdlib.h>
 #include <string.h>
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 JNIEXPORT void JNICALL
 Java_com_sun_security_auth_module_UnixSystem_getUnixInfo
                                                 (JNIEnv *env, jobject obj) {
--- a/jdk/src/jdk.security.auth/windows/native/libjaas/nt.c	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/src/jdk.security.auth/windows/native/libjaas/nt.c	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
  */
 
 #include <jni.h>
+#include "jni_util.h"
 #include "com_sun_security_auth_module_NTSystem.h"
 
 #include <windows.h>
@@ -49,6 +50,11 @@
         (*env)->ThrowNew(env, clazz, msg);
 }
 
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
 JNIEXPORT jlong JNICALL
 Java_com_sun_security_auth_module_NTSystem_getImpersonationToken0
         (JNIEnv *env, jobject obj) {
--- a/jdk/test/ProblemList.txt	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 21:00:20 2017 +0200
@@ -363,6 +363,18 @@
 # 8062512
 java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.java generic-all
 
+# 8076458
+java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java generic-all
+
+# 8130337
+java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java generic-all
+
+# 8080165, 8085982
+java/util/Arrays/ParallelPrefix.java generic-all
+
+# 8079538
+java/util/BitSet/BitSetStreamTest.java generic-all
+
 ############################################################################
 
 # jdk_instrument
--- a/jdk/test/TEST.groups	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/TEST.groups	Wed Jul 05 21:00:20 2017 +0200
@@ -28,7 +28,9 @@
 tier1 = \
     :jdk_lang \
     -java/lang/ProcessHandle/TreeTest.java \
+    -java/util/zip/TestLocalTime.java \
     :jdk_util \
+    -java/util/concurrent/Phaser/Basic.java \
     sun/nio/cs/ISO8859x.java \
     java/nio/Buffer \
     com/sun/crypto/provider/Cipher \
@@ -36,6 +38,8 @@
 
 tier2 = \
     java/lang/ProcessHandle/TreeTest.java \
+    java/util/zip/TestLocalTime.java \
+    java/util/concurrent/Phaser/Basic.java \
     :jdk_io \
     :jdk_nio \
     -sun/nio/cs/ISO8859x.java \
--- a/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/com/sun/jndi/ldap/LdapTimeoutTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -47,6 +47,7 @@
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLHandshakeException;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
@@ -234,6 +235,12 @@
         if (e.getCause() instanceof SocketTimeoutException) {
             // SSL connect will timeout via readReply using
             // SocketTimeoutException
+            e.printStackTrace();
+            pass();
+        } else if (e.getCause() instanceof SSLHandshakeException
+                && e.getCause().getCause() instanceof EOFException) {
+            // test seems to be failing intermittently on some
+            // platforms.
             pass();
         } else {
             fail(e);
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1248,7 +1248,7 @@
                 () -> p.toHandle(),
                 () -> p.supportsNormalTermination(),
                 () -> p.children(),
-                () -> p.allChildren());
+                () -> p.descendants());
 
     }
 
--- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -129,7 +129,7 @@
                 printf("         You can try to increase the timeout or%n");
                 printf("         you can try to use a faster VM (i.e. not a debug version).%n");
             }
-            children = getAllChildren(procHandle);
+            children = getDescendants(procHandle);
 
             ConcurrentHashMap<ProcessHandle, CompletableFuture<ProcessHandle>> completions =
                     new ConcurrentHashMap<>();
--- a/jdk/test/java/lang/ProcessHandle/PermissionTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/ProcessHandle/PermissionTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -62,9 +62,9 @@
     }
 
     @Test
-    public void allChildrenWithPermission() {
+    public void descendantsWithPermission() {
         Policy.setPolicy(new TestPolicy(new RuntimePermission("manageProcess")));
-        currentHndl.allChildren();
+        currentHndl.descendants();
     }
 
     @Test
@@ -122,7 +122,7 @@
 
     @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class)
     public void noPermissionAllChildren() {
-        currentHndl.allChildren();
+        currentHndl.descendants();
     }
 
     @Test(groups = { "NoManageProcessPermission" }, expectedExceptions = SecurityException.class)
--- a/jdk/test/java/lang/ProcessHandle/ProcessUtil.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/ProcessHandle/ProcessUtil.java	Wed Jul 05 21:00:20 2017 +0200
@@ -63,8 +63,8 @@
      * @param ph the Process to get children of
      * @return a list of child ProcessHandles
      */
-    public static List<ProcessHandle> getAllChildren(ProcessHandle ph) {
-        return ph.allChildren()
+    public static List<ProcessHandle> getDescendants(ProcessHandle ph) {
+        return ph.descendants()
                 .filter(ProcessUtil::isNotWindowsConsole)
                 .collect(Collectors.toList());
     }
@@ -117,7 +117,7 @@
                     // ignore
                 }
             }
-            subprocesses = getAllChildren(ph);
+            subprocesses = getDescendants(ph);
             count = subprocesses.size();
             System.out.printf(" waiting for subprocesses of %s to start," +
                     " expected: %d, current: %d%n", ph, nchildren, count);
@@ -133,7 +133,7 @@
      * @return the ProcessHandle
      */
     public static ProcessHandle destroyProcessTree(ProcessHandle p) {
-        Stream<ProcessHandle> children = p.allChildren().filter(ProcessUtil::isNotWindowsConsole);
+        Stream<ProcessHandle> children = p.descendants().filter(ProcessUtil::isNotWindowsConsole);
         children.forEach(ph -> {
             System.out.printf("destroyProcessTree destroyForcibly%n");
             printProcess(ph);
--- a/jdk/test/java/lang/ProcessHandle/TreeTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -193,21 +193,21 @@
             }
 
             // show the complete list of children (for debug)
-            List<ProcessHandle> allChildren = getAllChildren(p1Handle);
-            printf(" allChildren:  %s%n",
-                    allChildren.stream().map(p -> p.getPid())
-                            .collect(Collectors.toList()));
+            List<ProcessHandle> descendants = getDescendants(p1Handle);
+            printf(" descendants:  %s%n",
+                    descendants.stream().map(p -> p.getPid())
+                           .collect(Collectors.toList()));
 
-            // Verify that all spawned children show up in the allChildren List
+            // Verify that all spawned children show up in the descendants  List
             processes.forEach((p, parent) -> {
                 Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p);
-                Assert.assertTrue(allChildren.contains(p), "Spawned child should be listed in allChildren: " + p);
+                Assert.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p);
             });
 
             // Closing JavaChild's InputStream will cause all children to exit
             p1.getOutputStream().close();
 
-            for (ProcessHandle p : allChildren) {
+            for (ProcessHandle p : descendants) {
                 try {
                     p.onExit().get();       // wait for the child to exit
                 } catch (ExecutionException e) {
@@ -228,9 +228,9 @@
     /**
      * Test destroy of processes.
      * A JavaChild is started and it starts three children.
-     * Each one is then checked to be alive and listed by allChildren
+     * Each one is then checked to be alive and listed by descendants
      * and forcibly destroyed.
-     * After they exit they should no longer be listed by allChildren.
+     * After they exit they should no longer be listed by descendants.
      */
     @Test
     public static void test3() {
@@ -263,24 +263,24 @@
             Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
                     "Timeout waiting for processes to start");
 
-            // Debugging; list allChildren that are not expected in processes
-            List<ProcessHandle> allChildren = ProcessUtil.getAllChildren(p1Handle);
-            long count = allChildren.stream()
+            // Debugging; list descendants that are not expected in processes
+            List<ProcessHandle> descendants = ProcessUtil.getDescendants(p1Handle);
+            long count = descendants.stream()
                     .filter(ph -> !processes.containsKey(ph))
                     .count();
             if (count > 0) {
-                allChildren.stream()
+                descendants.stream()
                     .filter(ph -> !processes.containsKey(ph))
                     .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: "));
                 ProcessUtil.logTaskList();
-                Assert.assertEquals(0, count, "Extra processes in allChildren");
+                Assert.assertEquals(0, count, "Extra processes in descendants");
             }
 
-            // Verify that all spawned children are alive, show up in the allChildren list
+            // Verify that all spawned children are alive, show up in the descendants list
             // then destroy them
             processes.forEach((p, parent) -> {
                 Assert.assertEquals(p.isAlive(), true, "Child should be alive: " + p);
-                Assert.assertTrue(allChildren.contains(p), "Spawned child should be listed in allChildren: " + p);
+                Assert.assertTrue(descendants.contains(p), "Spawned child should be listed in descendants: " + p);
                 p.destroyForcibly();
             });
             Assert.assertEquals(processes.size(), newChildren, "Wrong number of children");
@@ -305,8 +305,8 @@
             p1.destroyForcibly();
             p1.waitFor();
 
-            // Verify that none of the spawned children are still listed by allChildren
-            List<ProcessHandle> remaining = getAllChildren(self);
+            // Verify that none of the spawned children are still listed by descendants
+            List<ProcessHandle> remaining = getDescendants(self);
             Assert.assertFalse(remaining.remove(p1Handle), "Child p1 should have exited");
             remaining = remaining.stream().filter(processes::containsKey).collect(Collectors.toList());
             Assert.assertEquals(remaining.size(), 0, "Subprocess(es) should have exited: " + remaining);
@@ -415,28 +415,28 @@
             Assert.assertTrue(spawnCount.await(Utils.adjustTimeout(30L), TimeUnit.SECONDS),
                     "Timeout waiting for processes to start");
 
-            // Debugging; list allChildren that are not expected in processes
-            List<ProcessHandle> allChildren = ProcessUtil.getAllChildren(p1Handle);
-            long count = allChildren.stream()
+            // Debugging; list descendants that are not expected in processes
+            List<ProcessHandle> descendants = ProcessUtil.getDescendants(p1Handle);
+            long count = descendants.stream()
                     .filter(ph -> !processes.containsKey(ph))
                     .count();
             if (count > 0) {
-                allChildren.stream()
+                descendants.stream()
                     .filter(ph -> !processes.containsKey(ph))
                     .forEach(ph1 -> ProcessUtil.printProcess(ph1, "Extra process: "));
                 ProcessUtil.logTaskList();
-                Assert.assertEquals(0, count, "Extra processes in allChildren");
+                Assert.assertEquals(0, count, "Extra processes in descendants");
             }
 
             Assert.assertEquals(getChildren(p1Handle).size(),
                     factor, "expected direct children");
-            count = getAllChildren(p1Handle).size();
+            count = getDescendants(p1Handle).size();
             long totalChildren = factor * factor * factor + factor * factor + factor;
             Assert.assertTrue(count >= totalChildren,
                     "expected at least " + totalChildren + ", actual: " + count);
 
-            List<ProcessHandle> subprocesses = getAllChildren(p1Handle);
-            printf(" allChildren:  %s%n",
+            List<ProcessHandle> subprocesses = getDescendants(p1Handle);
+            printf(" descendants:  %s%n",
                     subprocesses.stream().map(p -> p.getPid())
                     .collect(Collectors.toList()));
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/Chars.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+    @test
+    @bug 8054307
+    @summary test chars() and codePoints()
+*/
+
+import java.util.Arrays;
+import java.util.Random;
+
+public class Chars {
+
+    public static void main(String[] args) {
+        Random r = new Random();
+        for (int i = 0; i < 10; i++) {
+            int n = 100 + r.nextInt(100);
+            char[] cc = new char[n];
+            int[]  ccExp = new int[n];
+            int[]  cpExp = new int[n];
+            // latin1
+            for (int j = 0; j < n; j++) {
+                cc[j] = (char)(ccExp[j] = cpExp[j] = r.nextInt(0x80));
+            }
+            testChars(cc, ccExp);
+            testCPs(cc, cpExp);
+
+            // bmp without surrogates
+            for (int j = 0; j < n; j++) {
+                cc[j] = (char)(ccExp[j] = cpExp[j] = r.nextInt(0x8000));
+            }
+            testChars(cc, ccExp);
+            testCPs(cc, cpExp);
+
+            // bmp with surrogates
+            int k = 0;
+            for (int j = 0; j < n; j++) {
+                if (j % 9 ==  5 && j + 1 < n) {
+                    int cp = 0x10000 + r.nextInt(2000);
+                    cpExp[k++] = cp;
+                    Character.toChars(cp, cc, j);
+                    ccExp[j] = cc[j];
+                    ccExp[j + 1] = cc[j + 1];
+                    j++;
+                } else {
+                    cc[j] = (char)(ccExp[j] = cpExp[k++] = r.nextInt(0x8000));
+                }
+            }
+            cpExp = Arrays.copyOf(cpExp, k);
+            testChars(cc, ccExp);
+            testCPs(cc, cpExp);
+        }
+    }
+
+    static void testChars(char[] cc, int[] expected) {
+        String str = new String(cc);
+        if (!Arrays.equals(expected, str.chars().toArray())) {
+            throw new RuntimeException("chars/codePoints() failed!");
+        }
+    }
+
+    static void testCPs(char[] cc, int[] expected) {
+        String str = new String(cc);
+        if (!Arrays.equals(expected, str.codePoints().toArray())) {
+            throw new RuntimeException("chars/codePoints() failed!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/CharAt.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.stream.IntStream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.charAt.
+ * @run testng/othervm -XX:+CompactStrings CharAt
+ * @run testng/othervm -XX:-CompactStrings CharAt
+ */
+
+public class CharAt extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_L1, new char[] { 'A' } },
+                new Object[] { STRING_L2, new char[] { 'A', 'B' } },
+                new Object[] { STRING_L4, new char[] { 'A', 'B', 'C', 'D' } },
+                new Object[] { STRING_LLONG,
+                        new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
+                new Object[] { STRING_U1, new char[] { '\uFF21' } },
+                new Object[] { STRING_U2, new char[] { '\uFF21', '\uFF22' } },
+                new Object[] { STRING_M12, new char[] { '\uFF21', 'A' } },
+                new Object[] { STRING_M11, new char[] { 'A', '\uFF21' } }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCharAt(String str, char[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            IntStream
+                                    .range(0, str.length())
+                                    .forEach(
+                                            i -> assertEquals(
+                                                    str.charAt(i),
+                                                    expected[i],
+                                                    String.format(
+                                                            "testing String(%s).charAt(%d), source : %s, ",
+                                                            escapeNonASCIIs(data),
+                                                            i, source)));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/CodePointAt.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.stream.IntStream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.codePointAt.
+ * @run testng/othervm -XX:+CompactStrings CodePointAt
+ * @run testng/othervm -XX:-CompactStrings CodePointAt
+ */
+
+public class CodePointAt extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_L1, new int[] { 'A' } },
+                new Object[] { STRING_L2, new int[] { 'A', 'B' } },
+                new Object[] { STRING_L4, new int[] { 'A', 'B', 'C', 'D' } },
+                new Object[] { STRING_LLONG,
+                        new int[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
+                new Object[] { STRING_U1, new int[] { '\uFF21' } },
+                new Object[] { STRING_U2, new int[] { '\uFF21', '\uFF22' } },
+                new Object[] { STRING_M12, new int[] { '\uFF21', 'A' } },
+                new Object[] { STRING_M11, new int[] { 'A', '\uFF21' } },
+                new Object[] {
+                        STRING_SUPPLEMENTARY,
+                        new int[] { Character.toCodePoint('\uD801', '\uDC00'),
+                                '\uDC00',
+                                Character.toCodePoint('\uD801', '\uDC01'),
+                                '\uDC01', '\uFF21', 'A' }, } };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCodePointAt(String str, int[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            IntStream
+                                    .range(0, str.length())
+                                    .forEach(
+                                            i -> assertEquals(
+                                                    str.codePointAt(i),
+                                                    expected[i],
+                                                    String.format(
+                                                            "testing String(%s).codePointAt(%d), source : %s, ",
+                                                            escapeNonASCIIs(data),
+                                                            i, source)));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/CodePointBefore.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.stream.IntStream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.codePointBefore.
+ * @run testng/othervm -XX:+CompactStrings CodePointBefore
+ * @run testng/othervm -XX:-CompactStrings CodePointBefore
+ */
+
+public class CodePointBefore extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_L1, new int[] { 'A' } },
+                new Object[] { STRING_L2, new int[] { 'A', 'B' } },
+                new Object[] { STRING_L4, new int[] { 'A', 'B', 'C', 'D' } },
+                new Object[] { STRING_LLONG,
+                        new int[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
+                new Object[] { STRING_U1, new int[] { '\uFF21' } },
+                new Object[] { STRING_U2, new int[] { '\uFF21', '\uFF22' } },
+                new Object[] { STRING_M12, new int[] { '\uFF21', 'A' } },
+                new Object[] { STRING_M11, new int[] { 'A', '\uFF21' } },
+                new Object[] {
+                        STRING_SUPPLEMENTARY,
+                        new int[] { '\uD801', Character.toCodePoint('\uD801', '\uDC00'),
+                                '\uD801', Character.toCodePoint('\uD801', '\uDC01'),
+                                '\uFF21', 'A' }, } };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCodePointBefore(String str, int[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            IntStream
+                                    .range(0, str.length())
+                                    .forEach(
+                                            i -> assertEquals(
+                                                    str.codePointBefore(i + 1),
+                                                    expected[i],
+                                                    String.format(
+                                                            "testing String(%s).codePointBefore(%d), source : %s, ",
+                                                            escapeNonASCIIs(data),
+                                                            i + 1, source)));
+                        });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/CodePointCount.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.codePointCount.
+ * @run testng/othervm -XX:+CompactStrings CodePointCount
+ * @run testng/othervm -XX:-CompactStrings CodePointCount
+ */
+
+public class CodePointCount extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] { new Object[] { STRING_EMPTY, 0, 0, 0 },
+                new Object[] { STRING_L1, 0, 1, 1 },
+                new Object[] { STRING_L1, 1, 1, 0 },
+                new Object[] { STRING_L2, 0, 2, 2 },
+                new Object[] { STRING_L2, 0, 1, 1 },
+                new Object[] { STRING_L2, 1, 2, 1 },
+                new Object[] { STRING_L4, 0, 4, 4 },
+                new Object[] { STRING_L4, 0, 1, 1 },
+                new Object[] { STRING_L4, 2, 4, 2 },
+                new Object[] { STRING_LLONG, 0, 8, 8 },
+                new Object[] { STRING_LLONG, 0, 5, 5 },
+                new Object[] { STRING_LLONG, 4, 8, 4 },
+                new Object[] { STRING_LLONG, 0, 7, 7 },
+                new Object[] { STRING_U1, 0, 1, 1 },
+                new Object[] { STRING_U2, 0, 2, 2 },
+                new Object[] { STRING_U2, 0, 1, 1 },
+                new Object[] { STRING_U2, 1, 2, 1 },
+                new Object[] { STRING_M12, 0, 2, 2 },
+                new Object[] { STRING_M12, 0, 1, 1 },
+                new Object[] { STRING_M12, 1, 2, 1 },
+                new Object[] { STRING_M11, 0, 2, 2 },
+                new Object[] { STRING_M11, 0, 1, 1 },
+                new Object[] { STRING_M11, 1, 2, 1 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 1, 1 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 2, 1 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 3, 2 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 5, 3 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 6, 4 },
+                new Object[] { STRING_SUPPLEMENTARY, 1, 4, 2 },
+                new Object[] { STRING_SUPPLEMENTARY, 1, 6, 4 },
+                new Object[] { STRING_SUPPLEMENTARY, 2, 4, 1 },};
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCodePointCount(String str, int beginIndex, int endIndex,
+            int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.codePointCount(beginIndex, endIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).codePointCount(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), beginIndex,
+                                            endIndex, source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/CompactString.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.testng.annotations.BeforeClass;
+
+/*
+ * Base class of tests for Compact String.
+ *
+ */
+public class CompactString {
+
+    final Map<String, Map<String, String>> map = new HashMap<>();
+
+    enum StringSources {
+        EMPTY(STRING_EMPTY, BYTE_ARRAY_EMTPY, CHAR_ARRAY_EMPTY,
+                POINT_ARRAY_EMTPY), LDUPLICATE(STRING_LDUPLICATE,
+                BYTE_ARRAY_LDUPLICATE, CHAR_ARRAY_LDUPLICATE,
+                POINT_ARRAY_LDUPLICATE), LLONG(STRING_LLONG, BYTE_ARRAY_LLONG,
+                CHAR_ARRAY_LLONG, POINT_ARRAY_LLONG), L1(STRING_L1,
+                BYTE_ARRAY_L1, CHAR_ARRAY_L1, POINT_ARRAY_L1), L2(STRING_L2,
+                BYTE_ARRAY_L2, CHAR_ARRAY_L2, POINT_ARRAY_L2), L4(STRING_L4,
+                BYTE_ARRAY_L4, CHAR_ARRAY_L4, POINT_ARRAY_L4), UDUPLICATE(
+                STRING_UDUPLICATE, BYTE_ARRAY_UDUPLICATE,
+                CHAR_ARRAY_UDUPLICATE, POINT_ARRAY_UDUPLICATE), U1(STRING_U1,
+                BYTE_ARRAY_U1, CHAR_ARRAY_U1, POINT_ARRAY_U1), U2(STRING_U2,
+                BYTE_ARRAY_U2, CHAR_ARRAY_U2, POINT_ARRAY_U2), MDUPLICATE1(
+                STRING_MDUPLICATE1, BYTE_ARRAY_MDUPLICATE1,
+                CHAR_ARRAY_MDUPLICATE1, POINT_ARRAY_MDUPLICATE1), MDUPLICATE2(
+                STRING_MDUPLICATE2, BYTE_ARRAY_MDUPLICATE2,
+                CHAR_ARRAY_MDUPLICATE2, POINT_ARRAY_MDUPLICATE2), MLONG1(
+                STRING_MLONG1, BYTE_ARRAY_MLONG1, CHAR_ARRAY_MLONG1,
+                POINT_ARRAY_MLONG1), MLONG2(STRING_MLONG2, BYTE_ARRAY_MLONG2,
+                CHAR_ARRAY_MLONG2, POINT_ARRAY_MLONG2), M11(STRING_M11,
+                BYTE_ARRAY_M11, CHAR_ARRAY_M11, POINT_ARRAY_M11), M12(
+                STRING_M12, BYTE_ARRAY_M12, CHAR_ARRAY_M12, POINT_ARRAY_M12), SUPPLEMENTARY(
+                STRING_SUPPLEMENTARY, BYTE_ARRAY_SUPPLEMENTARY,
+                CHAR_ARRAY_SUPPLEMENTARY, POINT_ARRAY_SUPPLEMENTARY), SUPPLEMENTARY_LOWERCASE(
+                STRING_SUPPLEMENTARY_LOWERCASE,
+                BYTE_ARRAY_SUPPLEMENTARY_LOWERCASE,
+                CHAR_ARRAY_SUPPLEMENTARY_LOWERCASE,
+                POINT_ARRAY_SUPPLEMENTARY_LOWERCASE);
+
+        private StringSources(String s, byte[] b, char[] c, int[] i) {
+            str = s;
+            ba = b;
+            ca = c;
+            ia = i;
+        }
+
+        String getString() {
+            return str;
+        }
+
+        byte[] getByteArray() {
+            return ba;
+        }
+
+        char[] getCharArray() {
+            return ca;
+        }
+
+        int[] getIntArray() {
+            return ia;
+        }
+
+        private final String str;
+        private final byte[] ba;
+        private final char[] ca;
+        private final int[] ia;
+    }
+
+    protected static final String DEFAULT_CHARSET_NAME = "UTF-8";
+    protected static final Charset DEFAULT_CHARSET = Charset
+            .forName(DEFAULT_CHARSET_NAME);
+
+    protected static final String STRING_EMPTY = "";
+    protected static final byte[] BYTE_ARRAY_EMTPY = new byte[0];
+    protected static final char[] CHAR_ARRAY_EMPTY = new char[0];
+    protected static final int[] POINT_ARRAY_EMTPY = new int[0];
+
+    protected static final String STRING_LDUPLICATE = "ABABABABAB";
+    protected static final byte[] BYTE_ARRAY_LDUPLICATE = new byte[] { 'A', 'B',
+            'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
+    protected static final char[] CHAR_ARRAY_LDUPLICATE = new char[] { 'A', 'B',
+            'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
+    protected static final int[] POINT_ARRAY_LDUPLICATE = new int[] { 'A', 'B',
+            'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
+
+    protected static final String STRING_LLONG = "ABCDEFGH";
+    protected static final byte[] BYTE_ARRAY_LLONG = new byte[] { 'A', 'B', 'C',
+            'D', 'E', 'F', 'G', 'H' };
+    protected static final char[] CHAR_ARRAY_LLONG = new char[] { 'A', 'B', 'C',
+            'D', 'E', 'F', 'G', 'H' };
+    protected static final int[] POINT_ARRAY_LLONG = new int[] { 'A', 'B', 'C',
+            'D', 'E', 'F', 'G', 'H' };
+
+    protected static final String STRING_L1 = "A";
+    protected static final byte[] BYTE_ARRAY_L1 = new byte[] { 'A' };
+    protected static final char[] CHAR_ARRAY_L1 = new char[] { 'A' };
+    protected static final int[] POINT_ARRAY_L1 = new int[] { 'A' };
+
+    protected static final String STRING_L2 = "AB";
+    protected static final byte[] BYTE_ARRAY_L2 = new byte[] { 'A', 'B' };
+    protected static final char[] CHAR_ARRAY_L2 = new char[] { 'A', 'B' };
+    protected static final int[] POINT_ARRAY_L2 = new int[] { 'A', 'B' };
+
+    protected static final String STRING_L4 = "ABCD";
+    protected static final byte[] BYTE_ARRAY_L4 = new byte[] { 'A', 'B', 'C', 'D' };
+    protected static final char[] CHAR_ARRAY_L4 = new char[] { 'A', 'B', 'C', 'D' };
+    protected static final int[] POINT_ARRAY_L4 = new int[] { 'A', 'B', 'C', 'D' };
+
+    /*
+     * Because right now ASCII is the default encoding parameter for source code
+     * in JDK build environment, so we escape them. same as below.
+     */
+    protected static final String STRING_UDUPLICATE = "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22";
+    protected static final byte[] BYTE_ARRAY_UDUPLICATE = getBytes(STRING_UDUPLICATE);
+    protected static final char[] CHAR_ARRAY_UDUPLICATE = new char[] { '\uFF21',
+            '\uFF22', '\uFF21', '\uFF22', '\uFF21', '\uFF22', '\uFF21',
+            '\uFF22', '\uFF21', '\uFF22' };
+    protected static final int[] POINT_ARRAY_UDUPLICATE = new int[] { '\uFF21',
+            '\uFF22', '\uFF21', '\uFF22', '\uFF21', '\uFF22', '\uFF21',
+            '\uFF22', '\uFF21', '\uFF22' };
+
+    protected static final String STRING_U1 = "\uFF21";
+    protected static final byte[] BYTE_ARRAY_U1 = getBytes(STRING_U1);
+    protected static final char[] CHAR_ARRAY_U1 = new char[] { '\uFF21' };
+    protected static final int[] POINT_ARRAY_U1 = new int[] { '\uFF21' };
+
+    protected static final String STRING_U2 = "\uFF21\uFF22";
+    protected static final byte[] BYTE_ARRAY_U2 = getBytes(STRING_U2);
+    protected static final char[] CHAR_ARRAY_U2 = new char[] { '\uFF21', '\uFF22' };
+    protected static final int[] POINT_ARRAY_U2 = new int[] { '\uFF21', '\uFF22' };
+
+    protected static final String STRING_MDUPLICATE1 = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A";
+    protected static final byte[] BYTE_ARRAY_MDUPLICATE1 = getBytes(STRING_MDUPLICATE1);
+    protected static final char[] CHAR_ARRAY_MDUPLICATE1 = new char[] { '\uFF21',
+            'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A' };
+    protected static final int[] POINT_ARRAY_MDUPLICATE1 = new int[] { '\uFF21',
+            'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A' };
+
+    protected static final String STRING_MDUPLICATE2 = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21";
+    protected static final byte[] BYTE_ARRAY_MDUPLICATE2 = getBytes(STRING_MDUPLICATE2);
+    protected static final char[] CHAR_ARRAY_MDUPLICATE2 = new char[] { 'A',
+            '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A',
+            '\uFF21' };
+    protected static final int[] POINT_ARRAY_MDUPLICATE2 = new int[] { 'A',
+            '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A',
+            '\uFF21' };
+
+    protected static final String STRING_MLONG1 = "A\uFF21B\uFF22C\uFF23D\uFF24E\uFF25F\uFF26G\uFF27H\uFF28";
+    protected static final byte[] BYTE_ARRAY_MLONG1 = getBytes(STRING_MLONG1);
+    protected static final char[] CHAR_ARRAY_MLONG1 = new char[] { 'A', '\uFF21',
+            'B', '\uFF22', 'C', '\uFF23', 'D', '\uFF24', 'E', '\uFF25', 'F',
+            '\uFF26', 'G', '\uFF27', 'H', '\uFF28' };
+    protected static final int[] POINT_ARRAY_MLONG1 = new int[] { 'A', '\uFF21',
+            'B', '\uFF22', 'C', '\uFF23', 'D', '\uFF24', 'E', '\uFF25', 'F',
+            '\uFF26', 'G', '\uFF27', 'H', '\uFF28' };
+
+    protected static final String STRING_MLONG2 = "\uFF21A\uFF22B\uFF23C\uFF24D\uFF25E\uFF26F\uFF27G\uFF28H";
+    protected static final byte[] BYTE_ARRAY_MLONG2 = getBytes(STRING_MLONG2);
+    protected static final char[] CHAR_ARRAY_MLONG2 = new char[] { '\uFF21', 'A',
+            '\uFF22', 'B', '\uFF23', 'C', '\uFF24', 'D', '\uFF25', 'E',
+            '\uFF26', 'F', '\uFF27', 'G', '\uFF28', 'H' };
+    protected static final int[] POINT_ARRAY_MLONG2 = new int[] { '\uFF21', 'A',
+            '\uFF22', 'B', '\uFF23', 'C', '\uFF24', 'D', '\uFF25', 'E',
+            '\uFF26', 'F', '\uFF27', 'G', '\uFF28', 'H' };
+
+    protected static final String STRING_M11 = "A\uFF21";
+    protected static final byte[] BYTE_ARRAY_M11 = getBytes(STRING_M11);
+    protected static final char[] CHAR_ARRAY_M11 = new char[] { 'A', '\uFF21' };
+    protected static final int[] POINT_ARRAY_M11 = new int[] { 'A', '\uFF21' };
+
+    protected static final String STRING_M12 = "\uFF21A";
+    protected static final byte[] BYTE_ARRAY_M12 = getBytes(STRING_M12);
+    protected static final char[] CHAR_ARRAY_M12 = new char[] { '\uFF21', 'A' };
+    protected static final int[] POINT_ARRAY_M12 = new int[] { '\uFF21', 'A' };
+
+    protected static final String STRING_SUPPLEMENTARY = "\uD801\uDC00\uD801\uDC01\uFF21A";
+    protected static final byte[] BYTE_ARRAY_SUPPLEMENTARY = getBytes(STRING_SUPPLEMENTARY);
+    protected static final char[] CHAR_ARRAY_SUPPLEMENTARY = new char[] {
+            '\uD801', '\uDC00', '\uD801', '\uDC01', '\uFF21', 'A' };
+    protected static final int[] POINT_ARRAY_SUPPLEMENTARY = new int[] {
+            '\uD801', '\uDC00', '\uD801', '\uDC01', '\uFF21', 'A' };
+
+    protected static final String STRING_SUPPLEMENTARY_LOWERCASE = "\uD801\uDC28\uD801\uDC29\uFF41a";
+    protected static final byte[] BYTE_ARRAY_SUPPLEMENTARY_LOWERCASE = getBytes(STRING_SUPPLEMENTARY_LOWERCASE);
+    protected static final char[] CHAR_ARRAY_SUPPLEMENTARY_LOWERCASE = new char[] {
+            '\uD801', '\uDC28', '\uD801', '\uDC29', '\uFF41', 'a' };
+    protected static final int[] POINT_ARRAY_SUPPLEMENTARY_LOWERCASE = new int[] {
+            '\uD801', '\uDC28', '\uD801', '\uDC29', '\uFF41', 'a' };
+
+    protected static final String SRC_BYTE_ARRAY_WITH_CHARSETNAME = "source from byte array with charset name";
+    protected static final String SRC_BYTE_ARRAY_WITH_CHARSET = "source from byte array with charset";
+    protected static final String SRC_CHAR_ARRAY = "source from char array";
+    protected static final String SRC_POINT_ARRAY = "source from code point array";
+    protected static final String SRC_STRING = "source from String";
+    protected static final String SRC_STRINGBUFFER = "source from StringBuffer";
+    protected static final String SRC_STRINGBUILDER = "source from StringBuilder";
+    protected static final String SRC_COPYVALUEOF = "source from copyValueOf from char array";
+    protected static final String SRC_VALUEOF = "source from valueOf from char array";
+
+    static {
+        System.out
+                .println(String
+                        .format("====== The platform's default charset is \"%s\", we're using \"%s\" for testing.",
+                                Charset.defaultCharset().name(),
+                                DEFAULT_CHARSET_NAME));
+    }
+
+    private static byte[] getBytes(String str) {
+        byte[] res = null;
+        try {
+            res = str.getBytes(DEFAULT_CHARSET_NAME);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            throw new RuntimeException("caught UnsupportedEncodingException!!!", e);
+        }
+        return res;
+    }
+
+    private void setUpOneString(String content, byte[] ba, char[] ca, int[] cpa)
+            throws UnsupportedEncodingException {
+        final Map<String, String> m = new HashMap<>();
+        m.put(SRC_BYTE_ARRAY_WITH_CHARSETNAME, new String(ba,
+                DEFAULT_CHARSET_NAME));
+        m.put(SRC_BYTE_ARRAY_WITH_CHARSET, new String(ba, DEFAULT_CHARSET));
+        m.put(SRC_CHAR_ARRAY, new String(ca));
+        m.put(SRC_POINT_ARRAY, new String(cpa, 0, cpa.length));
+        m.put(SRC_STRING, new String(content));
+        m.put(SRC_STRINGBUFFER, new String(new StringBuffer(content)));
+        m.put(SRC_STRINGBUILDER, new String(new StringBuilder(content)));
+        m.put(SRC_COPYVALUEOF, String.copyValueOf(ca));
+        m.put(SRC_VALUEOF, String.valueOf(ca));
+        map.put(content, m);
+    }
+
+    /*
+     * Set up the test data, use 9 ways to construct one String.
+     *
+     * @throws UnsupportedEncodingException
+     *         If the named charset is not supported in setUpOneString(xxx).
+     */
+    @BeforeClass
+    public void setUp() throws UnsupportedEncodingException {
+        for (StringSources src : StringSources.values()) {
+            setUpOneString(src.getString(), src.getByteArray(),
+                    src.getCharArray(), src.getIntArray());
+        }
+    }
+
+    /*
+     * Because right now system default charset in JPRT environment is only
+     * guaranteed to support ASCII characters in log, so we escape them.
+     */
+    protected String escapeNonASCIIs(String str) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            if (c > 0x7F) {
+                sb.append("\\u").append(Integer.toHexString((int) c));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /*
+     * Because right now system default charset in JPRT environment is only
+     * guaranteed to support ASCII characters in log, so we escape them.
+     */
+    protected String escapeNonASCII(char c) {
+        StringBuilder sb = new StringBuilder();
+        if (c > 0x7F) {
+            sb.append("\\u").append(Integer.toHexString((int) c));
+        } else {
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/CompareTo.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.compareTo.
+ * @run testng/othervm -XX:+CompactStrings CompareTo
+ * @run testng/othervm -XX:-CompactStrings CompareTo
+ */
+
+public class CompareTo extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, "A", -1 },
+                new Object[] { STRING_EMPTY, "\uFF21", -1 },
+                new Object[] { STRING_L1, "AB", -1 },
+                new Object[] { STRING_L1, "A", 0 },
+                new Object[] { STRING_L1, "a", -32 },
+                new Object[] { STRING_L1, "\uFF21", -65248 },
+                new Object[] { STRING_L2, "AB", 0 },
+                new Object[] { STRING_L2, "Ab", -32 },
+                new Object[] { STRING_L2, "AA", 1 },
+                new Object[] { STRING_L2, "\uFF21", -65248 },
+                new Object[] { STRING_L2, "A\uFF21", -65247 },
+                new Object[] { STRING_L4, "ABC", 1 },
+                new Object[] { STRING_L4, "AB", 2 },
+                new Object[] { STRING_L4, "ABcD", -32 },
+                new Object[] { STRING_L4, "ABCD\uFF21\uFF21", -2 },
+                new Object[] { STRING_L4, "ABCD\uFF21", -1 },
+                new Object[] { STRING_LLONG, "ABCDEFG\uFF21", -65241 },
+                new Object[] { STRING_LLONG, "AB", 6 },
+                new Object[] { STRING_LLONG, "ABCD", 4 },
+                new Object[] { STRING_LLONG, "ABCDEFGH\uFF21\uFF21", -2 },
+                new Object[] { STRING_U1, "\uFF21", 0 },
+                new Object[] { STRING_U1, "\uFF22", -1 },
+                new Object[] { STRING_U1, "\uFF21\uFF22", -1 },
+                new Object[] { STRING_U1, "A", 65248 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
+                new Object[] { STRING_U2, "\uFF22", -1 },
+                new Object[] { STRING_U2, "\uFF21\uFF21", 1 },
+                new Object[] { STRING_U2, "A", 65248 },
+                new Object[] { STRING_M12, "\uFF21A", 0 },
+                new Object[] { STRING_M12, "A\uFF21", 65248 },
+                new Object[] { STRING_M12, "\uFF21\uFF21", -65248 },
+                new Object[] { STRING_M11, "A\uFF21", 0 },
+                new Object[] { STRING_M11, "\uFF21A", -65248 },
+                new Object[] { STRING_M11, "AA", 65248 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCompareTo(String str, String anotherString, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.compareTo(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).compareTo(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/CompareToIgnoreCase.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.compareToIgnoreCase.
+ * @run testng/othervm -XX:+CompactStrings CompareToIgnoreCase
+ * @run testng/othervm -XX:-CompactStrings CompareToIgnoreCase
+ */
+
+public class CompareToIgnoreCase extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", -1 },
+                new Object[] { STRING_L1, "a", 0 },
+                new Object[] { STRING_L1, "A", 0 },
+                new Object[] { STRING_L1, "\uFF21", -65248 },
+                new Object[] { STRING_L1, "B", -1 },
+                new Object[] { STRING_L2, "AB", 0 },
+                new Object[] { STRING_L2, "aB", 0 },
+                new Object[] { STRING_L2, "\uFF21", -65248 },
+                new Object[] { STRING_L2, "A\uFF21", -65247 },
+                new Object[] { STRING_L4, "ABCD", 0 },
+                new Object[] { STRING_L4, "abcd", 0 },
+                new Object[] { STRING_L4, "ABc\uFF21", -65245 },
+                new Object[] { STRING_LLONG, "ABCDEFGH", 0 },
+                new Object[] { STRING_LLONG, "abcdefgh", 0 },
+                new Object[] { STRING_LLONG, "ABCDEFG\uFF21", -65241 },
+                new Object[] { STRING_LLONG, "abcdefg\uFF21", -65241 },
+                new Object[] { STRING_U1, "\uFF41", 0 },
+                new Object[] { STRING_U1,
+                        "\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48", -7 },
+                new Object[] { STRING_U1, "A", 65248 },
+                new Object[] { STRING_U2, "\uFF41", 1 },
+                new Object[] { STRING_U2, "\uFF41\uFF42", 0 },
+                new Object[] { STRING_U2,
+                        "\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48", -6 },
+                new Object[] { STRING_M12, "\uFF41a", 0 },
+                new Object[] { STRING_M12, "\uFF41\uFF42", -65249 },
+                new Object[] { STRING_M11, "a\uFF41", 0 },
+                new Object[] { STRING_M11, "a\uFF42", -1 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCompareToIgnoreCase(String str, String anotherString,
+            int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.compareToIgnoreCase(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).compareToIgnoreCase(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Concat.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.concat.
+ * @run testng/othervm -XX:+CompactStrings Concat
+ * @run testng/othervm -XX:-CompactStrings Concat
+ */
+
+public class Concat extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_EMPTY, "ABC", "ABC" },
+                new Object[] { STRING_EMPTY,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "ABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_EMPTY,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_L1,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "AABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_L1,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "A\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_L2,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "ABABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_L2,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "AB\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_L4,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "ABCDABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_L4,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "ABCD\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_LLONG,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "ABCDEFGHABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_LLONG,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "ABCDEFGH\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_U1,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "\uFF21ABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_U1,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "\uFF21\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_U2,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "\uFF21\uFF22ABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_U2,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "\uFF21\uFF22\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_M12,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "\uFF21AABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_M12,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "\uFF21A\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_M11,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "A\uFF21ABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_M11,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "A\uFF21\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testConcat(String str, String anotherString, String expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.concat(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).concat(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Contains.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.contains.
+ * @run testng/othervm -XX:+CompactStrings Contains
+ * @run testng/othervm -XX:-CompactStrings Contains
+ */
+
+public class Contains extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, "", true },
+                new Object[] { STRING_EMPTY, "A", false },
+                new Object[] { STRING_EMPTY, "\uFF21", false },
+                new Object[] { STRING_L1, "", true },
+                new Object[] { STRING_L1, "A", true },
+                new Object[] { STRING_L1, "\uFF21", false },
+                new Object[] { STRING_L2, "", true },
+                new Object[] { STRING_L2, "A", true },
+                new Object[] { STRING_L2, "AB", true },
+                new Object[] { STRING_L2, "B", true },
+                new Object[] { STRING_L2, "ABC", false },
+                new Object[] { STRING_L2, "ab", false },
+                new Object[] { STRING_L4, "ABCD", true },
+                new Object[] { STRING_L4, "BC", true },
+                new Object[] { STRING_LLONG, "ABCDEFGH", true },
+                new Object[] { STRING_LLONG, "BCDEFGH", true },
+                new Object[] { STRING_LLONG, "EF", true },
+                new Object[] { STRING_U1, "", true },
+                new Object[] { STRING_U1, "\uFF21", true },
+                new Object[] { STRING_U1, "a", false },
+                new Object[] { STRING_U1, "\uFF21B", false },
+                new Object[] { STRING_U2, "", true },
+                new Object[] { STRING_U2, "\uFF21\uFF22", true },
+                new Object[] { STRING_U2, "a", false },
+                new Object[] { STRING_U2, "\uFF21B", false },
+                new Object[] { STRING_M12, "\uFF21A", true },
+                new Object[] { STRING_M12, "\uFF21", true },
+                new Object[] { STRING_M12, "A", true },
+                new Object[] { STRING_M12, "A\uFF21", false },
+                new Object[] { STRING_M11, "A\uFF21", true },
+                new Object[] { STRING_M11, "Ab", false }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testContains(String str, String anotherString, boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.contains(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).contains(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/EndsWith.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.endsWith.
+ * @run testng/othervm -XX:+CompactStrings EndsWith
+ * @run testng/othervm -XX:-CompactStrings EndsWith
+ */
+
+public class EndsWith extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] { new Object[] { STRING_EMPTY, "", true },
+                new Object[] { STRING_EMPTY, "A", false },
+                new Object[] { STRING_L1, "A", true },
+                new Object[] { STRING_L1, "", true },
+                new Object[] { STRING_L1, " ", false },
+                new Object[] { STRING_L2, "AB", true },
+                new Object[] { STRING_L2, "B", true },
+                new Object[] { STRING_L2, "", true },
+                new Object[] { STRING_L2, "A", false },
+                new Object[] { STRING_L4, "ABCD", true },
+                new Object[] { STRING_L4, "CD", true },
+                new Object[] { STRING_L4, "D", true },
+                new Object[] { STRING_L4, "", true },
+                new Object[] { STRING_L4, "BC", false },
+                new Object[] { STRING_LLONG, "ABCDEFGH", true },
+                new Object[] { STRING_LLONG, "EFGH", true },
+                new Object[] { STRING_LLONG, "", true },
+                new Object[] { STRING_LLONG, "CDEF", false },
+                new Object[] { STRING_LLONG, "\uFF28", false },
+                new Object[] { STRING_U1, "\uFF21", true },
+                new Object[] { STRING_U1, "", true },
+                new Object[] { STRING_U1, "\uFF22", false },
+                new Object[] { STRING_U1, "B", false },
+                new Object[] { STRING_U2, "\uFF21\uFF22", true },
+                new Object[] { STRING_U2, "\uFF22", true },
+                new Object[] { STRING_U2, "", true },
+                new Object[] { STRING_U2, "\uFF21", false },
+                new Object[] { STRING_M12, "\uFF21A", true },
+                new Object[] { STRING_M12, "A", true },
+                new Object[] { STRING_M12, "", true },
+                new Object[] { STRING_M12, "AA", false },
+                new Object[] { STRING_M11, "A\uFF21", true },
+                new Object[] { STRING_M11, "\uFF21", true },
+                new Object[] { STRING_M11, "", true },
+                new Object[] { STRING_M11, "\uFF21\uFF21", false }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testEndsWith(String str, String suffix, boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.endsWith(suffix),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).endsWith(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(suffix), source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Equals.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.equals.
+ * @run testng/othervm -XX:+CompactStrings Equals
+ * @run testng/othervm -XX:-CompactStrings Equals
+ */
+
+public class Equals extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_EMPTY, "", true },
+                new Object[] { STRING_EMPTY, "A", false },
+                new Object[] { STRING_EMPTY, new StringBuffer(""), false },
+                new Object[] { STRING_L1, "A", true },
+                new Object[] { STRING_L1, "", false },
+                new Object[] { STRING_L1, new StringBuffer("A"), false },
+                new Object[] { STRING_L2, "AB", true },
+                new Object[] { STRING_L2, "", false },
+                new Object[] { STRING_L2, new StringBuilder("AB"), false },
+                new Object[] { STRING_L4, "ABCD", true },
+                new Object[] { STRING_L4, "abc", false },
+                new Object[] { STRING_L4, "", false },
+                new Object[] { STRING_LLONG, "ABCDEFGH", true },
+                new Object[] { STRING_LLONG, "ABCDEFG", false },
+                new Object[] { STRING_LLONG, new StringBuilder("ABCDEFGH"),
+                        false },
+                new Object[] { STRING_U1, "\uFF21", true },
+                new Object[] { STRING_U1, "", false },
+                new Object[] { STRING_U2, "\uFF21\uFF22", true },
+                new Object[] { STRING_U2, "\uFF21", false },
+                new Object[] { STRING_U2, "", false },
+                new Object[] { STRING_U2, new StringBuilder("\uFF21\uFF22"),
+                        false },
+                new Object[] { STRING_M12, "\uFF21A", true },
+                new Object[] { STRING_M12, "A\uFF21", false },
+                new Object[] { STRING_M11, "A\uFF21", true },
+                new Object[] { STRING_M11, new StringBuilder("\uFF21A"), false }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testEquals(String str, Object obj, boolean expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.equals(obj), expected, String.format(
+                            "testing String(%s).equals(%s), source : %s, ",
+                            escapeNonASCIIs(data),
+                            escapeNonASCIIs(obj.toString()), source));
+                });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/EqualsIgnoreCase.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.equalsIgnoreCase.
+ * @run testng/othervm -XX:+CompactStrings EqualsIgnoreCase
+ * @run testng/othervm -XX:-CompactStrings EqualsIgnoreCase
+ */
+
+public class EqualsIgnoreCase extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, "", true },
+                new Object[] { STRING_L1, "a", true },
+                new Object[] { STRING_L2, "aB", true },
+                new Object[] { STRING_L4, "AbCd", true },
+                new Object[] { STRING_LLONG, "aBcDeFgH", true },
+                new Object[] { STRING_U1, "\uFF41", true },
+                new Object[] { STRING_U1, "\uFF21", true },
+                new Object[] { STRING_U2, "\uFF41\uFF42", true },
+                new Object[] { STRING_U2, "\uFF41\uFF22", true },
+                new Object[] { STRING_U2, "\uFF21\uFF42", true },
+                new Object[] { STRING_M12, "\uFF41a", true },
+                new Object[] { STRING_M12, "\uFF21A", true },
+                new Object[] { STRING_M11, "a\uFF41", true },
+                new Object[] { STRING_M11, "A\uFF21", true },
+
+        };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testEqualsIgnoreCase(String str, String anotherString,
+            boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.equalsIgnoreCase(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).equalsIgnoreCase(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/GetChars.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.Arrays;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.getChars.
+ * @run testng/othervm -XX:+CompactStrings GetChars
+ * @run testng/othervm -XX:-CompactStrings GetChars
+ */
+
+public class GetChars extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, 0, STRING_EMPTY.length(),
+                        new char[STRING_EMPTY.length()], 0, CHAR_ARRAY_EMPTY },
+                new Object[] { STRING_L1, 0, STRING_L1.length(),
+                        new char[STRING_L1.length()], 0, CHAR_ARRAY_L1 },
+                new Object[] { STRING_L2, 0, STRING_L2.length(),
+                        new char[STRING_L2.length()], 0, CHAR_ARRAY_L2 },
+                new Object[] { STRING_L4, 0, STRING_L4.length(),
+                        new char[STRING_L4.length()], 0, CHAR_ARRAY_L4 },
+                new Object[] { STRING_LLONG, 0, STRING_LLONG.length(),
+                        new char[STRING_LLONG.length()], 0, CHAR_ARRAY_LLONG },
+                new Object[] { STRING_U1, 0, STRING_U1.length(),
+                        new char[STRING_U1.length()], 0, CHAR_ARRAY_U1 },
+                new Object[] { STRING_U2, 0, STRING_U2.length(),
+                        new char[STRING_U2.length()], 0, CHAR_ARRAY_U2 },
+                new Object[] { STRING_M12, 0, STRING_M12.length(),
+                        new char[STRING_M12.length()], 0, CHAR_ARRAY_M12 },
+                new Object[] { STRING_M11, 0, STRING_M11.length(),
+                        new char[STRING_M11.length()], 0, CHAR_ARRAY_M11 },
+                new Object[] { STRING_UDUPLICATE, 0,
+                        STRING_UDUPLICATE.length(),
+                        new char[STRING_UDUPLICATE.length()], 0,
+                        CHAR_ARRAY_UDUPLICATE },
+                new Object[] { STRING_MDUPLICATE1, 0,
+                        STRING_MDUPLICATE1.length(),
+                        new char[STRING_MDUPLICATE1.length()], 0,
+                        CHAR_ARRAY_MDUPLICATE1 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testGetChars(String str, int srcBegin, int srcEnd, char[] dst,
+            int dstBegin, char[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            data.getChars(srcBegin, srcEnd, dst, dstBegin);
+                            assertTrue(
+                                    Arrays.equals(dst, expected),
+                                    String.format(
+                                            "testing String(%s).getChars(%d, %d, %s, %d), source : %s, ",
+                                            escapeNonASCIIs(data), srcBegin,
+                                            srcEnd, escapeNonASCIIs(Arrays
+                                                    .toString(dst)), dstBegin,
+                                            source));
+                        });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/IndexOf.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.indexOf.
+ * @run testng/othervm -XX:+CompactStrings IndexOf
+ * @run testng/othervm -XX:-CompactStrings IndexOf
+ */
+
+public class IndexOf extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, (int) 'A', -1 },
+                new Object[] { STRING_L1, (int) 'A', 0 },
+                new Object[] { STRING_L2, (int) 'A', 0 },
+                new Object[] { STRING_L2, (int) 'B', 1 },
+                new Object[] { STRING_L4, (int) 'A', 0 },
+                new Object[] { STRING_L4, (int) 'D', 3 },
+                new Object[] { STRING_L4, (int) 'E', -1 },
+                new Object[] { STRING_LLONG, (int) 'A', 0 },
+                new Object[] { STRING_LLONG, (int) 'H', 7 },
+                new Object[] { STRING_U1, (int) '\uFF21', 0 },
+                new Object[] { STRING_U1, (int) 'A', -1 },
+                new Object[] { STRING_U2, (int) '\uFF21', 0 },
+                new Object[] { STRING_U2, (int) '\uFF22', 1 },
+                new Object[] { STRING_M12, (int) '\uFF21', 0 },
+                new Object[] { STRING_M12, (int) 'A', 1 },
+                new Object[] { STRING_M11, (int) 'A', 0 },
+                new Object[] { STRING_M11, (int) '\uFF21', 1 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 0 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 1 },
+                new Object[] { STRING_SUPPLEMENTARY, 'A', 5 },
+                new Object[] { STRING_SUPPLEMENTARY, '\uFF21', 4 },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        Character.toCodePoint('\uD801', '\uDC00'), 0 },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        Character.toCodePoint('\uD801', '\uDC01'), 2 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testIndexOf(String str, int ch, int expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.indexOf(ch), expected, String.format(
+                            "testing String(%s).indexOf(%d), source : %s, ",
+                            escapeNonASCIIs(data), ch, source));
+                });
+    }
+
+    @DataProvider
+    public Object[][] provider2() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, (int) 'A', 0, -1 },
+                new Object[] { STRING_L1, (int) 'A', 0, 0 },
+                new Object[] { STRING_L1, (int) 'A', 1, -1 },
+                new Object[] { STRING_L1, (int) 'B', 0, -1 },
+                new Object[] { STRING_L2, (int) 'A', 0, 0 },
+                new Object[] { STRING_L2, (int) 'A', 1, -1 },
+                new Object[] { STRING_L2, (int) 'B', 0, 1 },
+                new Object[] { STRING_L2, (int) 'B', 1, 1 },
+                new Object[] { STRING_L4, (int) 'A', 0, 0 },
+                new Object[] { STRING_L4, (int) 'D', 2, 3 },
+                new Object[] { STRING_L4, (int) 'B', 2, -1 },
+                new Object[] { STRING_LLONG, (int) 'A', 0, 0 },
+                new Object[] { STRING_LLONG, (int) 'H', 5, 7 },
+                new Object[] { STRING_U1, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_U1, (int) 'A', 0, -1 },
+                new Object[] { STRING_U2, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_U2, (int) '\uFF22', 0, 1 },
+                new Object[] { STRING_M12, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_M12, (int) 'A', 1, 1 },
+                new Object[] { STRING_M11, (int) 'A', 0, 0 },
+                new Object[] { STRING_M11, (int) '\uFF21', 1, 1 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 1, 2 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 1, 1 }, };
+    }
+
+    @Test(dataProvider = "provider2")
+    public void testIndexOf(String str, int ch, int fromIndex, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.indexOf(ch, fromIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).indexOf(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), ch,
+                                            fromIndex, source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider3() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", -1 },
+                new Object[] { STRING_L1, "A", 0 },
+                new Object[] { STRING_L1, "AB", -1 },
+                new Object[] { STRING_L2, "A", 0 },
+                new Object[] { STRING_L2, "B", 1 },
+                new Object[] { STRING_L2, "AB", 0 },
+                new Object[] { STRING_L2, "AC", -1 },
+                new Object[] { STRING_L2, "ABC", -1 },
+                new Object[] { STRING_L4, "ABCD", 0 },
+                new Object[] { STRING_L4, "D", 3 },
+                new Object[] { STRING_LLONG, "ABCDEFGH", 0 },
+                new Object[] { STRING_LLONG, "EFGH", 4 },
+                new Object[] { STRING_LLONG, "EFGHI", -1 },
+                new Object[] { STRING_U1, "\uFF21", 0 },
+                new Object[] { STRING_U1, "\uFF21A", -1 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
+                new Object[] { STRING_U2, "\uFF22", 1 },
+                new Object[] { STRING_U2, "A\uFF22", -1 },
+                new Object[] { STRING_M12, "\uFF21A", 0 },
+                new Object[] { STRING_M12, "A", 1 },
+                new Object[] { STRING_M12, "\uFF21\uFF21", -1 },
+                new Object[] { STRING_M11, "A\uFF21", 0 },
+                new Object[] { STRING_M11, "\uFF21", 1 },
+                new Object[] { STRING_M11, "A", 0 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        0 },
+                new Object[] { STRING_UDUPLICATE,
+                        "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21", 1 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21",
+                        -1 }, };
+    }
+
+    @Test(dataProvider = "provider3")
+    public void testIndexOf(String str, String anotherString, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.indexOf(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).indexOf(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider4() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", 0, -1 },
+                new Object[] { STRING_L1, "A", 0, 0 },
+                new Object[] { STRING_L1, "A", 1, -1 },
+                new Object[] { STRING_L1, "AB", 0, -1 },
+                new Object[] { STRING_L2, "A", 0, 0 },
+                new Object[] { STRING_L2, "B", 0, 1 },
+                new Object[] { STRING_L2, "AB", 0, 0 },
+                new Object[] { STRING_L2, "AB", 1, -1 },
+                new Object[] { STRING_L4, "ABCD", 0, 0 },
+                new Object[] { STRING_L4, "BC", 0, 1 },
+                new Object[] { STRING_L4, "A", 0, 0 },
+                new Object[] { STRING_L4, "CD", 0, 2 },
+                new Object[] { STRING_L4, "A", 2, -1 },
+                new Object[] { STRING_L4, "ABCDE", 0, -1 },
+                new Object[] { STRING_LLONG, "ABCDEFGH", 0, 0 },
+                new Object[] { STRING_LLONG, "DEFGH", 0, 3 },
+                new Object[] { STRING_LLONG, "A", 0, 0 },
+                new Object[] { STRING_LLONG, "GHI", 0, -1 },
+                new Object[] { STRING_U1, "\uFF21", 0, 0 },
+                new Object[] { STRING_U1, "\uFF21A", 0, -1 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0, 0 },
+                new Object[] { STRING_U2, "\uFF22", 0, 1 },
+                new Object[] { STRING_U2, "\uFF21", 1, -1 },
+                new Object[] { STRING_M12, "\uFF21A", 0, 0 },
+                new Object[] { STRING_M12, "A", 1, 1 },
+                new Object[] { STRING_M12, "\uFF21A", 1, -1 },
+                new Object[] { STRING_M12, "\uFF21", 0, 0 },
+                new Object[] { STRING_M11, "A\uFF21", 0, 0 },
+                new Object[] { STRING_M11, "\uFF21", 1, 1 },
+                new Object[] { STRING_M11, "A\uFF21", 1, -1 },
+                new Object[] { STRING_M11, "A\uFF21A", 0, -1 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        0, 0 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        1, -1 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        1, 1 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22",
+                        4, 4 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22",
+                        7, -1 }, };
+    }
+
+    @Test(dataProvider = "provider4")
+    public void testIndexOf(String str, String anotherString, int fromIndex,
+            int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.indexOf(anotherString, fromIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).indexOf(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            fromIndex, source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Intern.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.intern.
+ * @run testng/othervm -XX:+CompactStrings Intern
+ * @run testng/othervm -XX:-CompactStrings Intern
+ */
+
+public class Intern extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "" },
+                new Object[] { STRING_L1, "A" },
+                new Object[] { STRING_LLONG, "ABCDEFGH" },
+                new Object[] { STRING_U1, "\uFF21" },
+                new Object[] { STRING_U2, "\uFF21\uFF22" },
+                new Object[] { STRING_M12, "\uFF21A" },
+                new Object[] { STRING_M11, "A\uFF21" },
+                new Object[] { STRING_MDUPLICATE1,
+                        "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testIntern(String str, String expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertTrue(data.intern() == expected, String.format(
+                            "testing String(%s).intern(), source : %s, ",
+                            escapeNonASCIIs(data), source));
+                });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/LastIndexOf.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.lastIndexOf.
+ * @run testng/othervm -XX:+CompactStrings LastIndexOf
+ * @run testng/othervm -XX:-CompactStrings LastIndexOf
+ */
+
+public class LastIndexOf extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, (int) 'A', -1 },
+                new Object[] { STRING_L1, (int) 'A', 0 },
+                new Object[] { STRING_L2, (int) 'A', 0 },
+                new Object[] { STRING_L2, (int) 'B', 1 },
+                new Object[] { STRING_L4, (int) 'A', 0 },
+                new Object[] { STRING_L4, (int) 'D', 3 },
+                new Object[] { STRING_LLONG, (int) 'A', 0 },
+                new Object[] { STRING_LLONG, (int) 'H', 7 },
+                new Object[] { STRING_U1, (int) '\uFF21', 0 },
+                new Object[] { STRING_U1, (int) 'B', -1 },
+                new Object[] { STRING_U2, (int) '\uFF21', 0 },
+                new Object[] { STRING_U2, (int) '\uFF22', 1 },
+                new Object[] { STRING_M12, (int) '\uFF21', 0 },
+                new Object[] { STRING_M12, (int) 'A', 1 },
+                new Object[] { STRING_M11, (int) 'A', 0 },
+                new Object[] { STRING_M11, (int) '\uFF21', 1 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 9 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 8 },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        Character.toCodePoint('\uD801', '\uDC01'), 2 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testLastIndexOf(String str, int ch, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.lastIndexOf(ch),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).lastIndexOf(%d), source : %s, ",
+                                            escapeNonASCIIs(data), ch, source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider2() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, (int) 'A', 0, -1 },
+                new Object[] { STRING_L1, (int) 'A', 0, 0 },
+                new Object[] { STRING_L1, (int) 'A', 1, 0 },
+                new Object[] { STRING_L2, (int) 'A', 0, 0 },
+                new Object[] { STRING_L2, (int) 'B', 1, 1 },
+                new Object[] { STRING_L2, (int) 'B', 2, 1 },
+                new Object[] { STRING_L4, (int) 'A', 0, 0 },
+                new Object[] { STRING_L4, (int) 'C', 2, 2 },
+                new Object[] { STRING_L4, (int) 'C', 1, -1 },
+                new Object[] { STRING_LLONG, (int) 'A', 0, 0 },
+                new Object[] { STRING_LLONG, (int) 'H', 7, 7 },
+                new Object[] { STRING_LLONG, (int) 'H', 6, -1 },
+                new Object[] { STRING_U1, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_U1, (int) '\uFF21', 7, 0 },
+                new Object[] { STRING_U2, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_U2, (int) '\uFF22', 0, -1 },
+                new Object[] { STRING_M12, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_M12, (int) 'A', 1, 1 },
+                new Object[] { STRING_M12, (int) 'A', 0, -1 },
+                new Object[] { STRING_M11, (int) 'A', 0, 0 },
+                new Object[] { STRING_M11, (int) '\uFF21', 1, 1 },
+                new Object[] { STRING_M11, (int) '\uFF21', 0, -1 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 5, 4 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 6, 6 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 5, 5 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 6, 5 }, };
+    }
+
+    @Test(dataProvider = "provider2")
+    public void testLastIndexOf(String str, int ch, int fromIndex, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.lastIndexOf(ch, fromIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).lastIndexOf(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), ch,
+                                            fromIndex, source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider3() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", -1 },
+                new Object[] { STRING_L1, "A", 0 },
+                new Object[] { STRING_L1, "AB", -1 },
+
+                new Object[] { STRING_L2, "AB", 0 },
+                new Object[] { STRING_L2, "B", 1 },
+                new Object[] { STRING_L4, "ABCD", 0 },
+                new Object[] { STRING_L4, "B", 1 },
+                new Object[] { STRING_LLONG, "ABCD", 0 },
+                new Object[] { STRING_LLONG, "GH", 6 },
+                new Object[] { STRING_U1, "\uFF21", 0 },
+                new Object[] { STRING_U1, "\uFF22", -1 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
+                new Object[] { STRING_U2, "\uFF22", 1 },
+                new Object[] { STRING_M12, "\uFF21A", 0 },
+                new Object[] { STRING_M12, "A", 1 },
+                new Object[] { STRING_M11, "A\uFF21", 0 },
+                new Object[] { STRING_M11, "\uFF21", 1 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22", 6 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", 8 }, };
+    }
+
+    @Test(dataProvider = "provider3")
+    public void testLastIndexOf(String str, String anotherString, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.lastIndexOf(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).lastIndexOf(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider4() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", 0, -1 },
+                new Object[] { STRING_L2, "AB", 0, 0 },
+
+                new Object[] { STRING_L1, "AB", -1, -1 },
+
+                new Object[] { STRING_L2, "B", 1, 1 },
+                new Object[] { STRING_L2, "B", 0, -1 },
+                new Object[] { STRING_L4, "ABC", 3, 0 },
+                new Object[] { STRING_L4, "ABC", 0, 0 },
+                new Object[] { STRING_L4, "ABC", 1, 0 },
+                new Object[] { STRING_L4, "BC", 1, 1 },
+                new Object[] { STRING_L4, "BC", 0, -1 },
+                new Object[] { STRING_LLONG, "ABCDEFGH", 0, 0 },
+                new Object[] { STRING_LLONG, "EFGH", 7, 4 },
+                new Object[] { STRING_LLONG, "EFGH", 3, -1 },
+                new Object[] { STRING_U1, "\uFF21", 0, 0 },
+                new Object[] { STRING_U1, "\uFF21", 7, 0 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0, 0 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 1, 0 },
+                new Object[] { STRING_M12, "\uFF21A", 0, 0 },
+                new Object[] { STRING_M12, "A", 1, 1 },
+                new Object[] { STRING_M12, "A", 0, -1 },
+                new Object[] { STRING_M11, "A\uFF21", 0, 0 },
+                new Object[] { STRING_M11, "A\uFF21", 1, 0 },
+                new Object[] { STRING_M11, "\uFF21", 0, -1 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        9, 0 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        0, 0 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", 6, 6 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21", 6, 6 }, };
+    }
+
+    @Test(dataProvider = "provider4")
+    public void testLastIndexOf(String str, String anotherString,
+            int fromIndex, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.lastIndexOf(anotherString, fromIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).lastIndexOf(%s, %d), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            fromIndex, source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Length.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.length.
+ * @run testng/othervm -XX:+CompactStrings Length
+ * @run testng/othervm -XX:-CompactStrings Length
+ */
+
+public class Length extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, 0 }, new Object[] { STRING_L1, 1 },
+                new Object[] { STRING_L2, 2 },
+                new Object[] { STRING_LLONG, 8 },
+                new Object[] { STRING_U1, 1 }, new Object[] { STRING_U2, 2 },
+                new Object[] { STRING_M12, 2 }, new Object[] { STRING_M11, 2 },
+                new Object[] { STRING_UDUPLICATE, 10 },
+                new Object[] { STRING_SUPPLEMENTARY, 6 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testLength(String str, int expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.length(), expected, String.format(
+                            "testing String(%s).length(), source : %s, ",
+                            escapeNonASCIIs(data), source));
+                });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Numbers.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is testing
+ *          Integer/Long's methods related to String.
+ * @run testng/othervm -XX:+CompactStrings Numbers
+ * @run testng/othervm -XX:-CompactStrings Numbers
+ */
+
+public class Numbers {
+
+    /*
+     * Data provider for testIntegerLong
+     *
+     * @return input parameter for testIntegerLong
+     */
+    @DataProvider
+    public Object[][] numbers() {
+        return new Object[][] {
+                { Integer.toBinaryString(Integer.MAX_VALUE),
+                        "1111111111111111111111111111111" },
+                { Integer.toBinaryString(Integer.MIN_VALUE),
+                        "10000000000000000000000000000000" },
+                { Integer.toBinaryString(7), "111" },
+                { Integer.toBinaryString(0), "0" },
+                { Integer.toOctalString(Integer.MAX_VALUE), "17777777777" },
+                { Integer.toOctalString(Integer.MIN_VALUE), "20000000000" },
+                { Integer.toOctalString(9), "11" },
+                { Integer.toOctalString(0), "0" },
+                { Integer.toHexString(Integer.MAX_VALUE), "7fffffff" },
+                { Integer.toHexString(Integer.MIN_VALUE), "80000000" },
+                { Integer.toHexString(17), "11" },
+                { Integer.toHexString(0), "0" },
+                { Integer.toString(Integer.MAX_VALUE, 2),
+                        "1111111111111111111111111111111" },
+                { Integer.toString(Integer.MIN_VALUE, 2),
+                        "-10000000000000000000000000000000" },
+                { Integer.toString(7, 2), "111" },
+                { Integer.toString(0, 2), "0" },
+                { Integer.toString(Integer.MAX_VALUE, 8), "17777777777" },
+                { Integer.toString(Integer.MIN_VALUE, 8), "-20000000000" },
+                { Integer.toString(9, 8), "11" },
+                { Integer.toString(Integer.MAX_VALUE, 16), "7fffffff" },
+                { Integer.toString(Integer.MIN_VALUE, 16), "-80000000" },
+                { Integer.toString(17, 16), "11" },
+                { Long.toBinaryString(Long.MAX_VALUE),
+                        "111111111111111111111111111111111111111111111111111111111111111" },
+                { Long.toBinaryString(Long.MIN_VALUE),
+                        "1000000000000000000000000000000000000000000000000000000000000000" },
+                { Long.toOctalString(Long.MAX_VALUE), "777777777777777777777" },
+                { Long.toOctalString(Long.MIN_VALUE), "1000000000000000000000" },
+                { Long.toHexString(Long.MAX_VALUE), "7fffffffffffffff" },
+                { Long.toHexString(Long.MIN_VALUE), "8000000000000000" },
+                { Long.toString(Long.MAX_VALUE, 2),
+                        "111111111111111111111111111111111111111111111111111111111111111" },
+                { Long.toString(Long.MIN_VALUE, 2),
+                        "-1000000000000000000000000000000000000000000000000000000000000000" },
+                { Long.toString(Long.MAX_VALUE, 8), "777777777777777777777" },
+                { Long.toString(Long.MIN_VALUE, 8), "-1000000000000000000000" },
+                { Long.toString(Long.MAX_VALUE, 16), "7fffffffffffffff" },
+                { Long.toString(Long.MIN_VALUE, 16), "-8000000000000000" } };
+    }
+
+    /*
+     * test Integer/Long's methods related to String.
+     *
+     * @param res
+     *            real result
+     * @param expected
+     *            expected result
+     */
+    @Test(dataProvider = "numbers")
+    public void testIntegerLong(String res, String expected) {
+        assertEquals(res, expected);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/OffsetByCodePoints.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.offsetByCodePoints.
+ * @run testng/othervm -XX:+CompactStrings OffsetByCodePoints
+ * @run testng/othervm -XX:-CompactStrings OffsetByCodePoints
+ */
+
+public class OffsetByCodePoints extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_SUPPLEMENTARY, 0, 1, 2 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 3, 5 },
+                new Object[] { STRING_SUPPLEMENTARY, 1, 1, 2 },
+                new Object[] { STRING_SUPPLEMENTARY, 1, 3, 5 },
+                new Object[] { STRING_SUPPLEMENTARY, 2, 1, 4 },
+                new Object[] { STRING_SUPPLEMENTARY, 2, 2, 5 },
+                new Object[] { STRING_SUPPLEMENTARY, 2, 3, 6 },
+                new Object[] { STRING_SUPPLEMENTARY, 3, 1, 4 },
+                new Object[] { STRING_SUPPLEMENTARY, 3, 2, 5 },
+                new Object[] { STRING_SUPPLEMENTARY, 3, 3, 6 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testOffsetByCodePoints(String str, int index,
+            int codePointOffset, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.offsetByCodePoints(index,
+                                            codePointOffset),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).offsetByCodePoints(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), index,
+                                            codePointOffset, source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/RegionMatches.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.regionMatches.
+ * @run testng/othervm -XX:+CompactStrings RegionMatches
+ * @run testng/othervm -XX:-CompactStrings RegionMatches
+ */
+
+public class RegionMatches extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, true, 0, "", 0, 0, true },
+                new Object[] { STRING_EMPTY, true, 0, "", 0, 1, false },
+                new Object[] { STRING_EMPTY, true, 0, "A", 0, 0, true },
+                new Object[] { STRING_EMPTY, true, 0, "", 0, 0, true },
+                new Object[] { STRING_EMPTY, true, 0, "", 0, 1, false },
+                new Object[] { STRING_L1, false, 0, "a", 0, 1, false },
+                new Object[] { STRING_L1, false, 0, "BA", 1, 1, true },
+                new Object[] { STRING_L1, false, 0, "Ba", 1, 1, false },
+                new Object[] { STRING_L1, true, 0, "a", 0, 1, true },
+                new Object[] { STRING_L1, true, 0, "BA", 1, 1, true },
+                new Object[] { STRING_L1, true, 0, "Ba", 1, 1, true },
+                new Object[] { STRING_L2, true, 1, "b", 0, 1, true },
+                new Object[] { STRING_L2, true, 1, "B", 0, 1, true },
+                new Object[] { STRING_L2, true, 0, "xaBc", 1, 2, true },
+                new Object[] { STRING_L2, false, 0, "AB", 0, 2, true },
+                new Object[] { STRING_L2, false, 0, "Ab", 0, 2, false },
+                new Object[] { STRING_L2, false, 1, "BAB", 2, 1, true },
+                new Object[] { STRING_LLONG, true, 1, "bCdEF", 0, 5, true },
+                new Object[] { STRING_LLONG, false, 2, "CDEFG", 0, 5, true },
+                new Object[] { STRING_LLONG, true, 2, "CDEFg", 0, 5, true },
+                new Object[] { STRING_U1, true, 0, "\uFF41", 0, 1, true },
+                new Object[] { STRING_U1, false, 0, "\uFF41", 0, 1, false },
+                new Object[] { STRING_MDUPLICATE1, true, 0, "\uFF41a\uFF41", 0,
+                        3, true },
+                new Object[] { STRING_MDUPLICATE1, false, 0, "\uFF21a\uFF21",
+                        0, 3, false },
+                new Object[] { STRING_SUPPLEMENTARY, true, 1, "\uDC00\uD801",
+                        0, 2, true },
+                new Object[] { STRING_SUPPLEMENTARY, true, 4, "\uFF21", 0, 1,
+                        true },
+                new Object[] { STRING_SUPPLEMENTARY, true, 5, "A", 0, 1, true },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 0,
+                        "\uD801\uDC28\uD801\uDC29", 0, 4, true },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 1,
+                        "\uDC28\uD801", 0, 2, true },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 1,
+                        "\uDC00\uD801", 0, 2, false },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 4,
+                        "\uFF21", 0, 1, true },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 4,
+                        "\uFF21", 0, 1, false },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 4,
+                        "\uFF41", 0, 1, true }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testRegionMatches(String str, boolean ignoreCase, int toffset,
+            String other, int ooffset, int len, boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.regionMatches(ignoreCase, toffset,
+                                            other, ooffset, len),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).regionMatches(%b, %d, %s, %d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), ignoreCase,
+                                            toffset, escapeNonASCIIs(other),
+                                            ooffset, len, source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Replace.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.replace.
+ * @run testng/othervm -XX:+CompactStrings Replace
+ * @run testng/othervm -XX:-CompactStrings Replace
+ */
+
+public class Replace extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_L1, 'A', 'B', "B" },
+                new Object[] { STRING_L1, 'A', 'A', "A" },
+                new Object[] { STRING_L1, 'A', '\uFF21', "\uFF21" },
+                new Object[] { STRING_L2, 'A', 'B', "BB" },
+                new Object[] { STRING_L2, 'B', 'A', "AA" },
+                new Object[] { STRING_L2, 'C', 'A', "AB" },
+                new Object[] { STRING_L2, 'B', '\uFF21', "A\uFF21" },
+                new Object[] { STRING_U1, '\uFF21', 'A', "A" },
+                new Object[] { STRING_U1, '\uFF22', 'A', "\uFF21" },
+                new Object[] { STRING_U2, '\uFF22', 'A', "\uFF21A" },
+                new Object[] { STRING_M12, 'A', '\uFF21', "\uFF21\uFF21" },
+                new Object[] { STRING_M11, '\uFF21', 'A', "AA" },
+                new Object[] { STRING_UDUPLICATE, '\uFF21', 'A',
+                        "A\uFF22A\uFF22A\uFF22A\uFF22A\uFF22" },
+                new Object[] { STRING_MDUPLICATE1, '\uFF21', 'A', "AAAAAAAAAA" },
+                new Object[] { STRING_MDUPLICATE1, 'A', '\uFF21',
+                        "\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21" }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testReplace(String str, char oldChar, char newChar,
+            String expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.replace(oldChar, newChar),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).replace(%s, %s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCII(oldChar),
+                                            escapeNonASCII(newChar), source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider2() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "", "ABC", "ABC" },
+                new Object[] { STRING_EMPTY, "", "", "" },
+                new Object[] { STRING_L1, "A", "B", "B" },
+                new Object[] { STRING_L1, "A", "A", "A" },
+                new Object[] { STRING_L2, "B", "\uFF21", "A\uFF21" },
+                new Object[] { STRING_LLONG, "BCD", "\uFF21", "A\uFF21EFGH" },
+                new Object[] { STRING_U1, "\uFF21", "A", "A" },
+                new Object[] { STRING_U1, "\uFF21", "A\uFF21", "A\uFF21" },
+                new Object[] { STRING_U2, "\uFF21", "A", "A\uFF22" },
+                new Object[] { STRING_U2, "\uFF22", "A", "\uFF21A" },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", "AB",
+                        "ABABABABAB" },
+                new Object[] { STRING_MDUPLICATE1, "\uFF21", "A", "AAAAAAAAAA" },
+                new Object[] { STRING_MDUPLICATE1, "A", "\uFF21",
+                        "\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21" }, };
+    }
+
+    @Test(dataProvider = "provider2")
+    public void testReplace(String str, CharSequence target,
+            CharSequence replacement, String expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.replace(target, replacement),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).replace(%s, %s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(target.toString()),
+                                            escapeNonASCIIs(replacement
+                                                    .toString()), source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/SerializationTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static jdk.testlibrary.SerializationUtils.*;
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SerializationUtils
+ * @summary Tests Compact String. This one is testing String serialization
+ *          among -XX:+CompactStrings/-XX:-CompactStrings/LegacyString
+ * @run testng/othervm -XX:+CompactStrings SerializationTest
+ * @run testng/othervm -XX:-CompactStrings SerializationTest
+ */
+
+public class SerializationTest {
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                // every byte array is serialized from corresponding String object
+                // by previous JDK(build 1.8.0_45-b14).
+                new Object[] { "", new byte[] { -84, -19, 0, 5, 116, 0, 0 } },
+                new Object[] { "A", new byte[] { -84, -19, 0, 5, 116, 0, 1, 65 } },
+                new Object[] { "AB", new byte[] { -84, -19, 0, 5, 116, 0, 2, 65, 66 } },
+                new Object[] { "abcdefghijk",
+                        new byte[] {-84, -19, 0, 5, 116, 0, 11, 97, 98, 99, 100, 101,
+                        102, 103, 104, 105, 106, 107 } },
+                new Object[] { "\uff21", new byte[] { -84, -19, 0, 5, 116, 0, 3, -17, -68, -95 } },
+                new Object[] { "\uff21\uff22", new byte[] { -84, -19, 0, 5, 116, 0, 6, -17, -68,
+                        -95, -17, -68, -94 } },
+                new Object[] { "\uff21A\uff21A\uff21A\uff21A\uff21A",
+                        new byte[] { -84, -19, 0, 5, 116, 0, 20, -17, -68, -95, 65, -17, -68,
+                        -95, 65, -17, -68, -95, 65, -17, -68, -95, 65, -17, -68, -95, 65 } },
+                new Object[] { "A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28",
+                        new byte[] { -84, -19, 0, 5, 116, 0, 32, 65, -17, -68, -95, 66, -17, -68,
+                        -94, 67, -17, -68, -93, 68, -17, -68, -92, 69, -17, -68, -91, 70, -17,
+                        -68, -90, 71, -17, -68, -89, 72, -17, -68, -88 } },
+                new Object[] { "\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H",
+                        new byte[] { -84, -19, 0, 5, 116, 0, 32, -17, -68, -95, 65, -17, -68,
+                        -94, 66, -17, -68, -93, 67, -17, -68, -92, 68, -17, -68, -91, 69, -17,
+                        -68, -90, 70, -17, -68, -89, 71, -17, -68, -88, 72 } },
+                new Object[] { "\ud801\udc00\ud801\udc01\uff21A",
+                        new byte[] { -84, -19, 0, 5, 116, 0, 16, -19, -96, -127, -19, -80, -128,
+                        -19, -96, -127, -19, -80, -127, -17, -68, -95, 65 } },
+                new Object[] { "\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22",
+                        new byte[] { -84, -19, 0, 5, 116, 0, 30, -17, -68, -95, -17, -68, -94, -17,
+                        -68, -95, -17, -68, -94, -17, -68, -95, -17, -68, -94, -17, -68, -95, -17,
+                        -68, -94, -17, -68, -95, -17, -68, -94 } } };
+    }
+
+    /*
+     * Verify serialization works between Compact String/Legacy String
+     */
+    @Test(dataProvider = "provider")
+    public void test(String strContent, byte[] baInJDK8) throws Exception {
+        // Serialize a String object into byte array.
+        byte[] ba = serialize(strContent);
+        assertEquals(ba, baInJDK8);
+        // Deserialize a String object from byte array which is generated by previous JDK(build 1.8.0_45-b14).
+        Object obj = deserialize(ba);
+        assertEquals(obj.getClass(), String.class);
+        assertEquals((String)obj, strContent);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Split.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.Arrays;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.split.
+ * @run testng/othervm -XX:+CompactStrings Split
+ * @run testng/othervm -XX:-CompactStrings Split
+ */
+
+public class Split extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_L1, "", 0, new String[] { "A" } },
+                new Object[] { STRING_L1, "", 1, new String[] { "A" } },
+                new Object[] { STRING_L1, "", 2, new String[] { "A", "" } },
+                new Object[] { STRING_L1, "A", 0, new String[] {} },
+                new Object[] { STRING_L2, "A", 0, new String[] { "", "B" } },
+                new Object[] { STRING_L2, "B", 0, new String[] { "A" } },
+                new Object[] { STRING_LLONG, "D", 0,
+                        new String[] { "ABC", "EFGH" } },
+                new Object[] { STRING_LLONG, "[D]", 0,
+                        new String[] { "ABC", "EFGH" } },
+                new Object[] { STRING_LLONG, "CD", 0,
+                        new String[] { "AB", "EFGH" } },
+                new Object[] { STRING_LLONG, "DC", 0,
+                        new String[] { "ABCDEFGH" } },
+                new Object[] { STRING_LLONG, "[CF]", 0,
+                        new String[] { "AB", "DE", "GH" } },
+                new Object[] { STRING_LLONG, "[CF]", 1,
+                        new String[] { "ABCDEFGH" } },
+                new Object[] { STRING_LLONG, "[CF]", 2,
+                        new String[] { "AB", "DEFGH" } },
+                new Object[] { STRING_LLONG, "[FC]", 0,
+                        new String[] { "AB", "DE", "GH" } },
+                new Object[] { STRING_LLONG, "[FC]", 1,
+                        new String[] { "ABCDEFGH" } },
+                new Object[] { STRING_LLONG, "[FC]", 2,
+                        new String[] { "AB", "DEFGH" } },
+                new Object[] { STRING_U1, "", 0, new String[] { "\uFF21" } },
+                new Object[] { STRING_U1, "", 1, new String[] { "\uFF21" } },
+                new Object[] { STRING_U1, "", 2, new String[] { "\uFF21", "" } },
+                new Object[] { STRING_U1, "\uFF21", 0, new String[] {} },
+                new Object[] { STRING_M12, "\uFF21", 0,
+                        new String[] { "", "A" } },
+                new Object[] { STRING_M12, "A", 0, new String[] { "\uFF21" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21",
+                        0,
+                        new String[] { "", "\uFF22", "\uFF22", "\uFF22",
+                                "\uFF22", "\uFF22" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21",
+                        2,
+                        new String[] { "",
+                                "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21",
+                        4,
+                        new String[] { "", "\uFF22", "\uFF22",
+                                "\uFF22\uFF21\uFF22\uFF21\uFF22" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF22",
+                        0,
+                        new String[] { "\uFF21", "\uFF21", "\uFF21", "\uFF21",
+                                "\uFF21" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF22",
+                        3,
+                        new String[] { "\uFF21", "\uFF21",
+                                "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22" } },
+
+                new Object[] { STRING_MDUPLICATE1, "\uFF21", 0,
+                        new String[] { "", "A", "A", "A", "A", "A" } },
+                new Object[] { STRING_MDUPLICATE1, "\uFF21", 3,
+                        new String[] { "", "A", "A\uFF21A\uFF21A\uFF21A" } },
+                new Object[] {
+                        STRING_MDUPLICATE1,
+                        "A",
+                        0,
+                        new String[] { "\uFF21", "\uFF21", "\uFF21", "\uFF21",
+                                "\uFF21" } },
+                new Object[] {
+                        STRING_MDUPLICATE1,
+                        "A",
+                        4,
+                        new String[] { "\uFF21", "\uFF21", "\uFF21",
+                                "\uFF21A\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "\uD801\uDC01", 0,
+                        new String[] { "\uD801\uDC00", "\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "\uDC01", 0,
+                        new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "\uD801\uDC01", 0,
+                        new String[] { "\uD801\uDC00", "\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 0,
+                        new String[] { "\uD801\uDC00", "", "A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 1,
+                        new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 2,
+                        new String[] { "\uD801\uDC00", "\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 0,
+                        new String[] { "\uD801\uDC00", "", "A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 1,
+                        new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 2,
+                        new String[] { "\uD801\uDC00", "\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, "\uDC01", 0,
+                        new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, "\uD801\uDC29",
+                        0, new String[] { "\uD801\uDC28", "\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uD801\uDC29\uFF41]", 0,
+                        new String[] { "\uD801\uDC28", "", "a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uD801\uDC29\uFF41]", 1,
+                        new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uD801\uDC29\uFF41]", 2,
+                        new String[] { "\uD801\uDC28", "\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uFF41\uD801\uDC29]", 0,
+                        new String[] { "\uD801\uDC28", "", "a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uFF41\uD801\uDC29]", 1,
+                        new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uFF41\uD801\uDC29]", 2,
+                        new String[] { "\uD801\uDC28", "\uFF41a" } }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testSplit(String str, String regex, int limit, String[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertTrue(
+                                    Arrays.equals(data.split(regex, limit),
+                                            expected),
+                                    String.format(
+                                            "testing String(%s).split(%s, %d), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(regex), limit,
+                                            source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/StartsWith.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.startsWith.
+ * @run testng/othervm -XX:+CompactStrings StartsWith
+ * @run testng/othervm -XX:-CompactStrings StartsWith
+ */
+
+public class StartsWith extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] {STRING_EMPTY, "", 0, true},
+                new Object[] {STRING_EMPTY, "A", 0, false},
+                new Object[] {STRING_EMPTY, "", 0, true},
+                new Object[] {STRING_EMPTY, "", -1, false},
+                new Object[] {STRING_L1, "A", 0, true},
+                new Object[] {STRING_L1, "A", -1, false},
+                new Object[] {STRING_L1, "A", 1, false},
+                new Object[] {STRING_L2, "B", 1, true},
+                new Object[] {STRING_L2, "B", 0, false},
+                new Object[] {STRING_L2, "A", 0, true},
+                new Object[] {STRING_L2, "AB", 1, false},
+                new Object[] {STRING_L4, "ABC", 0, true},
+                new Object[] {STRING_LLONG, "ABCDEFGH", 0, true},
+                new Object[] {STRING_LLONG, "ABCDE", 0, true},
+                new Object[] {STRING_LLONG, "CDE", 0, false},
+                new Object[] {STRING_LLONG, "FG", 5, true},
+                new Object[] {STRING_U1, "\uFF21", 0, true},
+                new Object[] {STRING_U1, "", 1, true},
+                new Object[] {STRING_U1, "\uFF21", 0, true},
+                new Object[] {STRING_U1, "A", 0, false},
+                new Object[] {STRING_U2, "\uFF21\uFF22", 0, true},
+                new Object[] {STRING_U2, "\uFF21", 0, true},
+                new Object[] {STRING_U2, "\uFF22", 0, false},
+                new Object[] {STRING_U2, "", 0, true},
+                new Object[] {STRING_M12, "\uFF21", 0, true},
+                new Object[] {STRING_M12, "\uFF21A", 0, true},
+                new Object[] {STRING_M12, "A", 0, false},
+                new Object[] {STRING_M12, "\uFF21A", 0, true},
+                new Object[] {STRING_M12, "A", 1, true},
+                new Object[] {STRING_M11, "A", 0, true},
+                new Object[] {STRING_M11, "A\uFF21", 0, true},
+                new Object[] {STRING_M11, "A\uFF21", 0, true},
+                new Object[] {STRING_M11, "\uFF21", 1, true},
+                new Object[] {STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        0, true},
+                new Object[] {STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 0, true},
+                new Object[] {STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 2, true},
+                new Object[] {STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 5, false},
+                new Object[] {STRING_MDUPLICATE1,
+                        "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A", 0, true},
+                new Object[] {STRING_MDUPLICATE1,
+                        "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21", 0, true},
+                new Object[] {STRING_MDUPLICATE1, "A\uFF21A\uFF21A\uFF21A", 1, true},
+                new Object[] {STRING_SUPPLEMENTARY, "\uDC01\uFF21", 3, true},
+        };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testStartsWith(String str, String prefix, int toffset,
+            boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.startsWith(prefix, toffset),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).startsWith(%s, %d), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(prefix), toffset,
+                                            source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/SubString.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.subString.
+ * @run testng/othervm -XX:+CompactStrings SubString
+ * @run testng/othervm -XX:-CompactStrings SubString
+ */
+
+public class SubString extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, 0, 0, "" },
+                new Object[] { STRING_L1, 0, 1, "A" },
+                new Object[] { STRING_L1, 1, 1, "" },
+                new Object[] { STRING_L2, 0, 2, "AB" },
+                new Object[] { STRING_L2, 1, 2, "B" },
+                new Object[] { STRING_LLONG, 0, 8, "ABCDEFGH" },
+                new Object[] { STRING_LLONG, 7, 8, "H" },
+                new Object[] { STRING_LLONG, 8, 8, "" },
+                new Object[] { STRING_LLONG, 3, 7, "DEFG" },
+                new Object[] { STRING_U1, 0, 1, "\uFF21" },
+                new Object[] { STRING_U1, 1, 1, "" },
+                new Object[] { STRING_U1, 0, 0, "" },
+                new Object[] { STRING_U2, 0, 2, "\uFF21\uFF22" },
+                new Object[] { STRING_U2, 1, 2, "\uFF22" },
+                new Object[] { STRING_U2, 2, 2, "" },
+                new Object[] { STRING_U2, 0, 2, "\uFF21\uFF22" },
+                new Object[] { STRING_U2, 1, 2, "\uFF22" },
+                new Object[] { STRING_M12, 1, 2, "A" },
+                new Object[] { STRING_M11, 0, 1, "A" },
+                new Object[] { STRING_M11, 1, 2, "\uFF21" },
+                new Object[] { STRING_UDUPLICATE, 1, 5,
+                        "\uFF22\uFF21\uFF22\uFF21" },
+                new Object[] { STRING_MDUPLICATE1, 9, 10, "A" },
+                new Object[] { STRING_MDUPLICATE1, 7, 8, "A" }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testSubstring(String str, int beginIndex, int endIndex,
+            String expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.substring(beginIndex, endIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).substring(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), beginIndex,
+                                            endIndex, source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/ToCharArray.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.Arrays;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.toCharArray.
+ * @run testng/othervm -XX:+CompactStrings ToCharArray
+ * @run testng/othervm -XX:-CompactStrings ToCharArray
+ */
+
+public class ToCharArray extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_EMPTY, new char[] {} },
+                new Object[] { STRING_L1, new char[] { 'A' } },
+                new Object[] { STRING_L2, new char[] { 'A', 'B' } },
+                new Object[] { STRING_LLONG,
+                        new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
+                new Object[] { STRING_U1, new char[] { '\uFF21' } },
+                new Object[] { STRING_U2, new char[] { '\uFF21', '\uFF22' } },
+                new Object[] { STRING_M12, new char[] { '\uFF21', 'A' } },
+                new Object[] { STRING_M11, new char[] { 'A', '\uFF21' } }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testToCharArray(String str, char[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertTrue(
+                                    Arrays.equals(data.toCharArray(), expected),
+                                    String.format(
+                                            "testing String(%s).toCharArray(), source : %s, ",
+                                            escapeNonASCIIs(data), source));
+                        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/ToLowerCase.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.toLowerCase.
+ * @run testng/othervm -XX:+CompactStrings ToLowerCase
+ * @run testng/othervm -XX:-CompactStrings ToLowerCase
+ */
+
+public class ToLowerCase extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_EMPTY, "" },
+                new Object[] { STRING_L1, "a" },
+                new Object[] { STRING_L2, "ab" },
+                new Object[] { STRING_U1, "\uFF41" },
+                new Object[] { STRING_MDUPLICATE1,
+                        "\uFF41a\uFF41a\uFF41a\uFF41a\uFF41a" },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        "\uD801\uDC28\uD801\uDC29\uFF41a" },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "\uD801\uDC28\uD801\uDC29\uFF41a" },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        STRING_SUPPLEMENTARY_LOWERCASE } };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testToLowerCase(String str, String expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.toLowerCase(), expected, String.format(
+                            "testing String(%s).toLowerCase(), source : %s, ",
+                            escapeNonASCIIs(data), source));
+                });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/ToUpperCase.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.toUpperCase.
+ * @run testng/othervm -XX:+CompactStrings ToUpperCase
+ * @run testng/othervm -XX:-CompactStrings ToUpperCase
+ */
+
+public class ToUpperCase extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "" },
+                new Object[] { STRING_L1, "A" },
+                new Object[] { STRING_L2, "AB" },
+                new Object[] { STRING_U1, "\uFF21" },
+                new Object[] { STRING_MDUPLICATE1,
+                        "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        "\uD801\uDC00\uD801\uDC01\uFF21A" },
+
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "\uD801\uDC00\uD801\uDC01\uFF21A" },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        STRING_SUPPLEMENTARY }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testToUpperCase(String str, String expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.toUpperCase(), expected, String.format(
+                            "testing String(%s).toUpperCase(), source : %s, ",
+                            escapeNonASCIIs(data), source));
+                });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/Trim.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.trim.
+ * @run testng/othervm -XX:+CompactStrings Trim
+ * @run testng/othervm -XX:-CompactStrings Trim
+ */
+
+public class Trim {
+
+    /*
+     * Data provider for testTrim
+     *
+     * @return input parameter for testTrim
+     */
+    @DataProvider
+    public Object[][] trims() {
+        return new Object[][] {
+                { " \t \t".trim(), "" },
+                { "\t \t ".trim(), "" },
+                { "\t A B C\t ".trim(), "A B C" },
+                { " \t A B C \t".trim(), "A B C" },
+                { "\t \uFF21 \uFF22 \uFF23\t ".trim(), "\uFF21 \uFF22 \uFF23" },
+                { " \t \uFF21 \uFF22 \uFF23 \t".trim(), "\uFF21 \uFF22 \uFF23" },
+                { " \t \uFF41 \uFF42 \uFF43 \t".trim(), "\uFF41 \uFF42 \uFF43" },
+                { " \t A\uFF21 B\uFF22 C\uFF23 \t".trim(),
+                        "A\uFF21 B\uFF22 C\uFF23" } };
+    }
+
+    /*
+     * test trim().
+     *
+     * @param res
+     *            real result
+     * @param expected
+     *            expected result
+     */
+    @Test(dataProvider = "trims")
+    public void testTrim(String res, String expected) {
+        assertEquals(res, expected);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/VMOptionsTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.lang.reflect.Field;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is testing
+ *          if Compact String enable/disable VM Options is indeed working in String class,
+ *          it's verified by testing if the VM option affect coder and
+ *          COMPACT_STRINGS field in String class.
+ * @run testng/othervm -XX:+CompactStrings -DCompactStringEnabled=true VMOptionsTest
+ * @run testng/othervm -XX:-CompactStrings -DCompactStringEnabled=false VMOptionsTest
+ */
+
+public class VMOptionsTest {
+    boolean compactStringEnabled;
+    // corresponding "COMPACT_STRINGS" field in String class.
+    Field COMPACT_STRINGS;
+    // corresponding "coder" field in String class.
+    Field coder;
+
+    // corresponding coder type in String class.
+    final byte LATIN1 = 0;
+    final byte UTF16  = 1;
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        compactStringEnabled = Boolean.valueOf(System.getProperty("CompactStringEnabled", null));
+        COMPACT_STRINGS = String.class.getDeclaredField("COMPACT_STRINGS");
+        COMPACT_STRINGS.setAccessible(true);
+        coder = String.class.getDeclaredField("coder");
+        coder.setAccessible(true);
+    }
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] {"", LATIN1},
+                new Object[] {"abc", LATIN1},
+                new Object[] {"A\uff21", UTF16},
+                new Object[] {"\uff21\uff22", UTF16}
+        };
+    }
+
+    /*
+     * verify the coder field in String objects.
+     */
+    @Test(dataProvider = "provider")
+    public void testCoder(String str, byte expected) throws Exception {
+        byte c = (byte) coder.get(str);
+        expected = compactStringEnabled ? expected : UTF16;
+        assertEquals(c, expected);
+    }
+
+    /*
+     * verify the COMPACT_STRINGS flag in String objects.
+     */
+    @Test(dataProvider = "provider")
+    public void testCompactStringFlag(String str, byte ignore) throws Exception {
+        assertTrue(COMPACT_STRINGS.get(str).equals(compactStringEnabled));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/CompactString/ValueOf.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.valueOf.
+ *          valueOf(char[] data) is not tested here.
+ * @run testng/othervm -XX:+CompactStrings ValueOf
+ * @run testng/othervm -XX:-CompactStrings ValueOf
+ */
+
+public class ValueOf {
+
+    /*
+     * Data provider for testValueOf
+     *
+     * @return input parameter for testValueOf
+     */
+    @DataProvider
+    public Object[][] valueOfs() {
+        return new Object[][] { { String.valueOf(true), "true" },
+                { String.valueOf(false), "false" },
+                { String.valueOf(1.0f), "1.0" },
+                { String.valueOf(0.0f), "0.0" },
+                { String.valueOf(Float.MAX_VALUE), "3.4028235E38" },
+                { String.valueOf(Float.MIN_VALUE), "1.4E-45" },
+                { String.valueOf(1.0d), "1.0" },
+                { String.valueOf(0.0d), "0.0" },
+                { String.valueOf(Double.MAX_VALUE), "1.7976931348623157E308" },
+                { String.valueOf(Double.MIN_VALUE), "4.9E-324" },
+                { String.valueOf(1), "1" }, { String.valueOf(0), "0" },
+                { String.valueOf(Integer.MAX_VALUE), "2147483647" },
+                { String.valueOf(Integer.MIN_VALUE), "-2147483648" },
+                { String.valueOf(1L), "1" }, { String.valueOf(0L), "0" },
+                { String.valueOf(Long.MAX_VALUE), "9223372036854775807" },
+                { String.valueOf(Long.MIN_VALUE), "-9223372036854775808" } };
+    }
+
+    /*
+     * test String.valueOf(xxx).
+     *
+     * @param res
+     *            real result
+     * @param expected
+     *            expected result
+     */
+    @Test(dataProvider = "valueOfs")
+    public void testValueOf(String res, String expected) {
+        assertEquals(res, expected);
+    }
+
+}
--- a/jdk/test/java/lang/String/LiteralReplace.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/String/LiteralReplace.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 8058779
+ * @bug 8058779 8054307
  * @library /lib/testlibrary/
  * @build jdk.testlibrary.RandomFactory
  * @run testng LiteralReplace
@@ -104,6 +104,109 @@
             {"abcdefgh", "[a-h]", "X", "abcdefgh"},
             {"aa+", "a+", "", "a"},
             {"^abc$", "abc", "x", "^x$"},
+
+            // more with non-latin1 characters
+            {"\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00",
+             "\u4e01",
+             "\u4e01\u4e00"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08",
+             "\u4e03\u4e04\u4e05",
+             "\u4e10\u4e11\u4e12",
+             "\u4e00\u4e01\u4e02\u4e10\u4e11\u4e12\u4e06\u4e07\u4e08"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08",
+             "ABC",
+             "\u4e10\u4e11\u4e12",
+             "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08",
+             "\u4e02\u4e03",
+             "\u4e12\u4e13",
+             "\u4e00\u4e01\u4e12\u4e13\u4e04\u4e12\u4e13\u4e07\u4e08"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08",
+             "\u4e02\u4e03",
+             "ab",
+             "\u4e00\u4e01ab\u4e04ab\u4e07\u4e08"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07",
+             "",
+             "_",
+             "_\u4e00_\u4e01_\u4e02_\u4e03_\u4e04_\u4e05_\u4e06_\u4e07_"},
+            {"^\u4e00\u4e01\u4e02$",
+             "\u4e00\u4e01\u4e02",
+             "\u4e03",
+             "^\u4e03$"},
+
+            {"", "\u4e00", "\u4e01", ""},
+            {"", "", "\u4e00\u4e01\u4e02", "\u4e00\u4e01\u4e02"},
+
+            {"^\u4e00\u4e01\u4e02$",
+             "\u4e00\u4e01\u4e02",
+             "X",
+             "^X$"},
+
+            {"abcdefgh",
+             "def",
+             "\u4e01",
+             "abc\u4e01gh"},
+
+            {"abcdefgh",
+             "def",
+             "\u4e01\u4e02",
+             "abc\u4e01\u4e02gh"},
+
+            {"abcdefabcgh",
+             "abc",
+             "\u4e01\u4e02",
+             "\u4e01\u4e02def\u4e01\u4e02gh"},
+
+            {"abcdefabcghabc",
+             "abc",
+             "\u4e01\u4e02",
+             "\u4e01\u4e02def\u4e01\u4e02gh\u4e01\u4e02"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
+             "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
+             "abcd",
+             "abcd"},
+
+            {"\u4e00\u4e01",
+             "\u4e00\u4e01",
+             "abcdefg",
+             "abcdefg"},
+
+            {"\u4e00\u4e01xyz",
+             "\u4e00\u4e01",
+             "abcdefg",
+             "abcdefgxyz"},
+
+            {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00",
+             "\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00"},
+
+            {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00",
+             "\u4e00\u4e00\u4e00\u4e00"},
+
+            {"\u4e00.\u4e01.\u4e02.\u4e03.\u4e04.",
+             ".",
+             "-",
+             "\u4e00-\u4e01-\u4e02-\u4e03-\u4e04-"},
+
+            {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
+             "\u4e00",
+             "",
+             ""},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
+             "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
+             "",
+             ""},
         };
     }
 
--- a/jdk/test/java/lang/String/ToLowerCase.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/String/ToLowerCase.java	Wed Jul 05 21:00:20 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
     @test
-    @bug 4217441 4533872 4900935 8020037 8032012 8041791 8042589
+    @bug 4217441 4533872 4900935 8020037 8032012 8041791 8042589 8054307
     @summary toLowerCase should lower-case Greek Sigma correctly depending
              on the context (final/non-final).  Also it should handle
              Locale specific (lt, tr, and az) lowercasings and supplementary
@@ -134,14 +134,60 @@
         }
         test(src.toString(), Locale.US, exp.toString());
 
+        // test latin1
+        src = new StringBuilder(0x100);
+        exp = new StringBuilder(0x100);
+        for (int cp = 0; cp < 0x100; cp++) {
+            int lowerCase = Character.toLowerCase(cp);
+            if (lowerCase == -1) {    //Character.ERROR
+                continue;
+            }
+            src.appendCodePoint(cp);
+            exp.appendCodePoint(lowerCase);
+        }
+        test(src.toString(), Locale.US, exp.toString());
+
+        // test non-latin1 -> latin1
+        src = new StringBuilder(0x100).append("abc");
+        exp = new StringBuilder(0x100).append("abc");
+        for (int cp = 0x100; cp < 0x10000; cp++) {
+            int lowerCase  = Character.toLowerCase(cp);
+            if (lowerCase < 0x100 && cp != '\u0130') {
+                src.appendCodePoint(cp);
+                exp.appendCodePoint(lowerCase);
+            }
+        }
+        test(src.toString(), Locale.US, exp.toString());
     }
 
     static void test(String in, Locale locale, String expected) {
+        test0(in, locale,expected);
+        for (String[] ss :  new String[][] {
+                                new String[] {"abc",      "abc"},
+                                new String[] {"aBc",      "abc"},
+                                new String[] {"ABC",      "abc"},
+                                new String[] {"ab\u4e00", "ab\u4e00"},
+                                new String[] {"aB\u4e00", "ab\u4e00"},
+                                new String[] {"AB\u4e00", "ab\u4e00"},
+                                new String[] {"ab\uD800\uDC00", "ab\uD800\uDC00"},
+                                new String[] {"aB\uD800\uDC00", "ab\uD800\uDC00"},
+                                new String[] {"AB\uD800\uDC00", "ab\uD800\uDC00"},
+                                new String[] {"ab\uD801\uDC1C", "ab\uD801\uDC44"},
+                                new String[] {"aB\uD801\uDC1C", "ab\uD801\uDC44"},
+                                new String[] {"AB\uD801\uDC1C", "ab\uD801\uDC44"},
+
+                            }) {
+            test0(ss[0] + " " + in, locale, ss[1] + " " + expected);
+            test0(in + " " + ss[0], locale, expected + " " + ss[1]);
+        }
+    }
+
+    static void test0(String in, Locale locale, String expected) {
         String result = in.toLowerCase(locale);
         if (!result.equals(expected)) {
             System.err.println("input: " + in + ", locale: " + locale +
                     ", expected: " + expected + ", actual: " + result);
             throw new RuntimeException();
         }
-   }
+    }
 }
--- a/jdk/test/java/lang/String/ToUpperCase.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/String/ToUpperCase.java	Wed Jul 05 21:00:20 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
     @test
-    @bug 4219630 4304573 4533872 4900935 8042589
+    @bug 4219630 4304573 4533872 4900935 8042589 8054307
     @summary toUpperCase should upper-case German sharp s correctly even if
              it's the only character in the string. should also uppercase
              all of the 1:M char mappings correctly.  Also it should handle
@@ -97,14 +97,66 @@
         test("A\uD801\uDC44", Locale.ROOT, "A\uD801\uDC1c");
         test("a\uD801\uDC28\uD801\uDC29\uD801\uDC2A", Locale.US, "A\uD801\uDC00\uD801\uDC01\uD801\uDC02");
         test("A\uD801\uDC28a\uD801\uDC29b\uD801\uDC2Ac", Locale.US, "A\uD801\uDC00A\uD801\uDC01B\uD801\uDC02C");
+
+        // test latin1 only case
+        StringBuilder src = new StringBuilder(0x100);
+        StringBuilder exp = new StringBuilder(0x100);
+        for (int cp = 0; cp < 0x100; cp++) {
+            int upperCase = Character.toUpperCase(cp);
+            if (upperCase == -1) {    //Character.ERROR
+                continue;
+            }
+            src.appendCodePoint(cp);
+            if (cp == '\u00df') {
+                exp.append("SS");     // need Character.toUpperCaseEx()
+            } else {
+                exp.appendCodePoint(upperCase);
+            }
+        }
+        test(src.toString(), Locale.US, exp.toString());
+
+        // test non-latin1 -> latin1
+        src = new StringBuilder(0x100).append("ABC");
+        exp = new StringBuilder(0x100).append("ABC");
+        for (int cp = 0x100; cp < 0x10000; cp++) {
+            int upperCase  = Character.toUpperCase(cp);
+            if (upperCase < 0x100) {
+                src.appendCodePoint(cp);
+                exp.appendCodePoint(upperCase);
+            }
+        }
+        test(src.toString(), Locale.US, exp.toString());
+
     }
 
     static void test(String in, Locale locale, String expected) {
+        test0(in, locale,expected);
+        // trigger different code paths
+        for (String[] ss :  new String[][] {
+                                new String[] {"abc",      "ABC"},
+                                new String[] {"AbC",      "ABC"},
+                                new String[] {"ABC",      "ABC"},
+                                new String[] {"AB\u4e00", "AB\u4e00"},
+                                new String[] {"ab\u4e00", "AB\u4e00"},
+                                new String[] {"aB\u4e00", "AB\u4e00"},
+                                new String[] {"AB\uD800\uDC00", "AB\uD800\uDC00"},
+                                new String[] {"Ab\uD800\uDC00", "AB\uD800\uDC00"},
+                                new String[] {"ab\uD800\uDC00", "AB\uD800\uDC00"},
+                                new String[] {"AB\uD801\uDC44", "AB\uD801\uDC1C"},
+                                new String[] {"Ab\uD801\uDC44", "AB\uD801\uDC1C"},
+                                new String[] {"ab\uD801\uDC44", "AB\uD801\uDC1C"},
+                            }) {
+            test0(ss[0] + " " + in, locale, ss[1] + " " + expected);
+            test0(in + " " + ss[0], locale, expected + " " + ss[1]);
+        }
+    }
+
+    static void test0(String in, Locale locale, String expected) {
         String result = in.toUpperCase(locale);
         if (!result.equals(expected)) {
             System.err.println("input: " + in + ", locale: " + locale +
                     ", expected: " + expected + ", actual: " + result);
             throw new RuntimeException();
         }
-   }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuffer/CompactStringBuffer.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.Arrays;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This test is testing StringBuffer
+ *          behavior related to Compact String.
+ * @run testng/othervm -XX:+CompactStrings CompactStringBuffer
+ * @run testng/othervm -XX:-CompactStrings CompactStringBuffer
+ */
+
+public class CompactStringBuffer {
+
+    /*
+     * Tests for "A"
+     */
+    @Test
+    public void testCompactStringBufferForLatinA() {
+        final String ORIGIN = "A";
+        /*
+         * Because right now ASCII is the default encoding parameter for source
+         * code in JDK build environment, so we escape them. same as below.
+         */
+        check(new StringBuffer(ORIGIN).append(new char[] { '\uFF21' }),
+                "A\uFF21");
+        check(new StringBuffer(ORIGIN).append(new StringBuffer("\uFF21")),
+                "A\uFF21");
+        check(new StringBuffer(ORIGIN).append("\uFF21"), "A\uFF21");
+        check(new StringBuffer(ORIGIN).append(new StringBuffer("\uFF21")),
+                "A\uFF21");
+        check(new StringBuffer(ORIGIN).delete(0, 1), "");
+        check(new StringBuffer(ORIGIN).delete(0, 0), "A");
+        check(new StringBuffer(ORIGIN).deleteCharAt(0), "");
+        assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), 0);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), -1);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0);
+        assertEquals(new StringBuffer(ORIGIN).insert(1, "\uD801\uDC00")
+                .indexOf("A", 0), 0);
+        assertEquals(new StringBuffer(ORIGIN).insert(0, "\uD801\uDC00")
+                .indexOf("A", 0), 2);
+        check(new StringBuffer(ORIGIN).insert(0, new char[] {}), "A");
+        check(new StringBuffer(ORIGIN).insert(1, new char[] { '\uFF21' }),
+                "A\uFF21");
+        check(new StringBuffer(ORIGIN).insert(0, new char[] { '\uFF21' }),
+                "\uFF21A");
+        check(new StringBuffer(ORIGIN).insert(0, new StringBuffer("\uFF21")),
+                "\uFF21A");
+        check(new StringBuffer(ORIGIN).insert(1, new StringBuffer("\uFF21")),
+                "A\uFF21");
+        check(new StringBuffer(ORIGIN).insert(0, ""), "A");
+        check(new StringBuffer(ORIGIN).insert(0, "\uFF21"), "\uFF21A");
+        check(new StringBuffer(ORIGIN).insert(1, "\uFF21"), "A\uFF21");
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 0);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), -1);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 1);
+        check(new StringBuffer(ORIGIN).replace(0, 0, "\uFF21"), "\uFF21A");
+        check(new StringBuffer(ORIGIN).replace(0, 1, "\uFF21"), "\uFF21");
+        checkSetCharAt(new StringBuffer(ORIGIN), 0, '\uFF21', "\uFF21");
+        checkSetLength(new StringBuffer(ORIGIN), 0, "");
+        checkSetLength(new StringBuffer(ORIGIN), 1, "A");
+        check(new StringBuffer(ORIGIN).substring(0), "A");
+        check(new StringBuffer(ORIGIN).substring(1), "");
+    }
+
+    /*
+     * Tests for "\uFF21"
+     */
+    @Test
+    public void testCompactStringBufferForNonLatinA() {
+        final String ORIGIN = "\uFF21";
+        check(new StringBuffer(ORIGIN).append(new char[] { 'A' }), "\uFF21A");
+        check(new StringBuffer(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
+        check(new StringBuffer(ORIGIN).append("A"), "\uFF21A");
+        check(new StringBuffer(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
+        check(new StringBuffer(ORIGIN).delete(0, 1), "");
+        check(new StringBuffer(ORIGIN).delete(0, 0), "\uFF21");
+        check(new StringBuffer(ORIGIN).deleteCharAt(0), "");
+        assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), -1);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), 0);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0);
+        check(new StringBuffer(ORIGIN).insert(0, new char[] {}), "\uFF21");
+        check(new StringBuffer(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21A");
+        check(new StringBuffer(ORIGIN).insert(0, new char[] { 'A' }), "A\uFF21");
+        check(new StringBuffer(ORIGIN).insert(0, new StringBuffer("A")),
+                "A\uFF21");
+        check(new StringBuffer(ORIGIN).insert(1, new StringBuffer("A")),
+                "\uFF21A");
+        check(new StringBuffer(ORIGIN).insert(0, ""), "\uFF21");
+        check(new StringBuffer(ORIGIN).insert(0, "A"), "A\uFF21");
+        check(new StringBuffer(ORIGIN).insert(1, "A"), "\uFF21A");
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), -1);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 0);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 1);
+        check(new StringBuffer(ORIGIN).replace(0, 0, "A"), "A\uFF21");
+        check(new StringBuffer(ORIGIN).replace(0, 1, "A"), "A");
+        checkSetCharAt(new StringBuffer(ORIGIN), 0, 'A', "A");
+        checkSetLength(new StringBuffer(ORIGIN), 0, "");
+        checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21");
+        check(new StringBuffer(ORIGIN).substring(0), "\uFF21");
+        check(new StringBuffer(ORIGIN).substring(1), "");
+    }
+
+    /*
+     * Tests for "\uFF21A"
+     */
+    @Test
+    public void testCompactStringBufferForMixedA1() {
+        final String ORIGIN = "\uFF21A";
+        check(new StringBuffer(ORIGIN).delete(0, 1), "A");
+        check(new StringBuffer(ORIGIN).delete(1, 2), "\uFF21");
+        check(new StringBuffer(ORIGIN).deleteCharAt(1), "\uFF21");
+        check(new StringBuffer(ORIGIN).deleteCharAt(0), "A");
+        assertEquals(new StringBuffer(ORIGIN).indexOf("A", 0), 1);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 0), 0);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("", 0), 0);
+        check(new StringBuffer(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21AA");
+        check(new StringBuffer(ORIGIN).insert(0, new char[] { '\uFF21' }),
+                "\uFF21\uFF21A");
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 1);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 0);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 2);
+        check(new StringBuffer(ORIGIN).replace(0, 0, "A"), "A\uFF21A");
+        check(new StringBuffer(ORIGIN).replace(0, 1, "A"), "AA");
+        checkSetCharAt(new StringBuffer(ORIGIN), 0, 'A', "AA");
+        checkSetLength(new StringBuffer(ORIGIN), 0, "");
+        checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21");
+        check(new StringBuffer(ORIGIN).substring(0), "\uFF21A");
+        check(new StringBuffer(ORIGIN).substring(1), "A");
+    }
+
+    /*
+     * Tests for "A\uFF21"
+     */
+    @Test
+    public void testCompactStringBufferForMixedA2() {
+        final String ORIGIN = "A\uFF21";
+        check(new StringBuffer(ORIGIN).replace(1, 2, "A"), "AA");
+        checkSetLength(new StringBuffer(ORIGIN), 1, "A");
+        check(new StringBuffer(ORIGIN).substring(0), "A\uFF21");
+        check(new StringBuffer(ORIGIN).substring(1), "\uFF21");
+        check(new StringBuffer(ORIGIN).substring(0, 1), "A");
+    }
+
+    /*
+     * Tests for "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A"
+     */
+    @Test
+    public void testCompactStringBufferForDuplicatedMixedA1() {
+        final String ORIGIN = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A";
+        checkSetLength(new StringBuffer(ORIGIN), 1, "\uFF21");
+        assertEquals(new StringBuffer(ORIGIN).indexOf("A", 5), 5);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 5), 6);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 9);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 8);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf(""), 10);
+        check(new StringBuffer(ORIGIN).substring(9), "A");
+        check(new StringBuffer(ORIGIN).substring(8), "\uFF21A");
+    }
+
+    /*
+     * Tests for "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21"
+     */
+    @Test
+    public void testCompactStringBufferForDuplicatedMixedA2() {
+        final String ORIGIN = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21";
+        checkSetLength(new StringBuffer(ORIGIN), 1, "A");
+        assertEquals(new StringBuffer(ORIGIN).indexOf("A", 5), 6);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21", 5), 5);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 8);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 9);
+        check(new StringBuffer(ORIGIN).substring(9), "\uFF21");
+        check(new StringBuffer(ORIGIN).substring(8), "A\uFF21");
+    }
+
+    /*
+     * Tests for "\uD801\uDC00\uD801\uDC01"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePoint() {
+        final String ORIGIN = "\uD801\uDC00\uD801\uDC01";
+        check(new StringBuffer(ORIGIN).append("A"), "\uD801\uDC00\uD801\uDC01A");
+        check(new StringBuffer(ORIGIN).append("\uFF21"),
+                "\uD801\uDC00\uD801\uDC01\uFF21");
+        check(new StringBuffer(ORIGIN).appendCodePoint('A'),
+                "\uD801\uDC00\uD801\uDC01A");
+        check(new StringBuffer(ORIGIN).appendCodePoint('\uFF21'),
+                "\uD801\uDC00\uD801\uDC01\uFF21");
+        assertEquals(new StringBuffer(ORIGIN).charAt(0), '\uD801');
+        assertEquals(new StringBuffer(ORIGIN).codePointAt(0),
+                Character.codePointAt(ORIGIN, 0));
+        assertEquals(new StringBuffer(ORIGIN).codePointAt(1),
+                Character.codePointAt(ORIGIN, 1));
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(2),
+                Character.codePointAt(ORIGIN, 0));
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2);
+        check(new StringBuffer(ORIGIN).delete(0, 2), "\uD801\uDC01");
+        check(new StringBuffer(ORIGIN).delete(0, 3), "\uDC01");
+        check(new StringBuffer(ORIGIN).deleteCharAt(1), "\uD801\uD801\uDC01");
+        checkGetChars(new StringBuffer(ORIGIN), 0, 3, new char[] { '\uD801',
+                '\uDC00', '\uD801' });
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uD801\uDC01"), 2);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uDC01"), 3);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21"), -1);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("A"), -1);
+        check(new StringBuffer(ORIGIN).insert(0, "\uFF21"),
+                "\uFF21\uD801\uDC00\uD801\uDC01");
+        check(new StringBuffer(ORIGIN).insert(1, "\uFF21"),
+                "\uD801\uFF21\uDC00\uD801\uDC01");
+        check(new StringBuffer(ORIGIN).insert(1, "A"),
+                "\uD801A\uDC00\uD801\uDC01");
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uDC00\uD801"), 1);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uD801"), 2);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), -1);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), -1);
+        assertEquals(new StringBuffer(ORIGIN).length(), 4);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 2);
+        check(new StringBuffer(ORIGIN).replace(0, 2, "A"), "A\uD801\uDC01");
+        check(new StringBuffer(ORIGIN).replace(0, 3, "A"), "A\uDC01");
+        check(new StringBuffer(ORIGIN).replace(0, 2, "\uFF21"),
+                "\uFF21\uD801\uDC01");
+        check(new StringBuffer(ORIGIN).replace(0, 3, "\uFF21"), "\uFF21\uDC01");
+        check(new StringBuffer(ORIGIN).reverse(), "\uD801\uDC01\uD801\uDC00");
+        checkSetCharAt(new StringBuffer(ORIGIN), 1, '\uDC01',
+                "\uD801\uDC01\uD801\uDC01");
+        checkSetCharAt(new StringBuffer(ORIGIN), 1, 'A', "\uD801A\uD801\uDC01");
+        checkSetLength(new StringBuffer(ORIGIN), 2, "\uD801\uDC00");
+        checkSetLength(new StringBuffer(ORIGIN), 3, "\uD801\uDC00\uD801");
+        check(new StringBuffer(ORIGIN).substring(1, 3), "\uDC00\uD801");
+    }
+
+    /*
+     * Tests for "A\uD801\uDC00\uFF21"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePointMixed1() {
+        final String ORIGIN = "A\uD801\uDC00\uFF21";
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(3),
+                Character.codePointAt(ORIGIN, 1));
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), '\uD801');
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), 'A');
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 2);
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 4), 3);
+        check(new StringBuffer(ORIGIN).delete(0, 1), "\uD801\uDC00\uFF21");
+        check(new StringBuffer(ORIGIN).delete(0, 1).delete(2, 3), "\uD801\uDC00");
+        check(new StringBuffer(ORIGIN).deleteCharAt(3).deleteCharAt(0),
+                "\uD801\uDC00");
+        assertEquals(new StringBuffer(ORIGIN).indexOf("\uFF21"), 3);
+        assertEquals(new StringBuffer(ORIGIN).indexOf("A"), 0);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("\uFF21"), 3);
+        assertEquals(new StringBuffer(ORIGIN).lastIndexOf("A"), 0);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 3);
+        check(new StringBuffer(ORIGIN).replace(1, 3, "A"), "AA\uFF21");
+        check(new StringBuffer(ORIGIN).replace(1, 4, "A"), "AA");
+        check(new StringBuffer(ORIGIN).replace(1, 4, ""), "A");
+        check(new StringBuffer(ORIGIN).reverse(), "\uFF21\uD801\uDC00A");
+        checkSetLength(new StringBuffer(ORIGIN), 1, "A");
+        check(new StringBuffer(ORIGIN).substring(0, 1), "A");
+    }
+
+    /*
+     * Tests for "\uD801\uDC00\uFF21A"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePointMixed2() {
+        final String ORIGIN = "\uD801\uDC00\uFF21A";
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(3),
+                Character.codePointAt(ORIGIN, 2));
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(2),
+                Character.codePointAt(ORIGIN, 0));
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), '\uD801');
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 2);
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 4), 3);
+        check(new StringBuffer(ORIGIN).delete(0, 2), "\uFF21A");
+        check(new StringBuffer(ORIGIN).delete(0, 3), "A");
+        check(new StringBuffer(ORIGIN).deleteCharAt(0).deleteCharAt(0)
+                .deleteCharAt(0), "A");
+        assertEquals(new StringBuffer(ORIGIN).indexOf("A"), 3);
+        assertEquals(new StringBuffer(ORIGIN).delete(0, 3).indexOf("A"), 0);
+        assertEquals(new StringBuffer(ORIGIN).replace(0, 3, "B").indexOf("A"),
+                1);
+        assertEquals(new StringBuffer(ORIGIN).substring(3, 4).indexOf("A"), 0);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 2);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3);
+        check(new StringBuffer(ORIGIN).replace(0, 3, "B"), "BA");
+        check(new StringBuffer(ORIGIN).reverse(), "A\uFF21\uD801\uDC00");
+    }
+
+    /*
+     * Tests for "\uD801A\uDC00\uFF21"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePointMixed3() {
+        final String ORIGIN = "\uD801A\uDC00\uFF21";
+        assertEquals(new StringBuffer(ORIGIN).codePointAt(1), 'A');
+        assertEquals(new StringBuffer(ORIGIN).codePointAt(3), '\uFF21');
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), '\uD801');
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), 'A');
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(3), '\uDC00');
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 3);
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2);
+        assertEquals(new StringBuffer(ORIGIN).delete(0, 1).delete(1, 3)
+                .indexOf("A"), 0);
+        assertEquals(
+                new StringBuffer(ORIGIN).replace(0, 1, "B").replace(2, 4, "C")
+                        .indexOf("A"), 1);
+        assertEquals(new StringBuffer(ORIGIN).substring(1, 4).substring(0, 1)
+                .indexOf("A"), 0);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3);
+        check(new StringBuffer(ORIGIN).reverse(), "\uFF21\uDC00A\uD801");
+    }
+
+    /*
+     * Tests for "A\uDC01\uFF21\uD801"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePointMixed4() {
+        final String ORIGIN = "A\uDC01\uFF21\uD801";
+        assertEquals(new StringBuffer(ORIGIN).codePointAt(1), '\uDC01');
+        assertEquals(new StringBuffer(ORIGIN).codePointAt(3), '\uD801');
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(1), 'A');
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(2), '\uDC01');
+        assertEquals(new StringBuffer(ORIGIN).codePointBefore(3), '\uFF21');
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(0, 3), 3);
+        assertEquals(new StringBuffer(ORIGIN).codePointCount(1, 3), 2);
+        assertEquals(new StringBuffer(ORIGIN).delete(1, 4).indexOf("A"), 0);
+        assertEquals(new StringBuffer(ORIGIN).replace(1, 4, "B").indexOf("A"),
+                0);
+        assertEquals(new StringBuffer(ORIGIN).substring(0, 1).indexOf("A"), 0);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(0, 1), 1);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(1, 1), 2);
+        assertEquals(new StringBuffer(ORIGIN).offsetByCodePoints(2, 1), 3);
+        check(new StringBuffer(ORIGIN).reverse(), "\uD801\uFF21\uDC01A");
+    }
+
+    @Test
+    public void testCompactStringMisc() {
+        String ascii = "abcdefgh";
+        String asciiMixed = "abc" + "\u4e00\u4e01\u4e02" + "fgh";
+        String bmp = "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08";
+        String bmpMixed = "\u4e00\u4e01\u4e02" + "ABC" + "\u4e06\u4e07\u4e08";
+
+        check(new StringBuffer().append(ascii).delete(0, 20).toString(),
+              "");
+        check(new StringBuffer().append(ascii).delete(3, 20).toString(),
+              "abc");
+        check(new StringBuffer().append(ascii).delete(3, 6).toString(),
+              "abcgh");
+        check(new StringBuffer().append(ascii).deleteCharAt(0).toString(),
+              "bcdefgh");
+        check(new StringBuffer().append(ascii).deleteCharAt(3).toString(),
+              "abcefgh");
+        check(new StringBuffer().append(asciiMixed).delete(3, 6).toString(),
+              "abcfgh");
+        check(new StringBuffer().append(asciiMixed).deleteCharAt(3).toString(),
+              "abc\u4e01\u4e02fgh");
+        check(new StringBuffer().append(asciiMixed).deleteCharAt(3)
+                                                   .deleteCharAt(3)
+                                                   .deleteCharAt(3).toString(),
+              "abcfgh");
+        check(new StringBuffer().append(bmp).delete(0, 20).toString(),
+              "");
+        check(new StringBuffer().append(bmp).delete(3, 20).toString(),
+              "\u4e00\u4e01\u4e02");
+        check(new StringBuffer().append(bmp).delete(3, 6).toString(),
+              "\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08");
+        check(new StringBuffer().append(bmp).deleteCharAt(0).toString(),
+              "\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08");
+        check(new StringBuffer().append(bmp).deleteCharAt(3).toString(),
+              "\u4e00\u4e01\u4e02\u4e04\u4e05\u4e06\u4e07\u4e08");
+        check(new StringBuffer().append(bmpMixed).delete(3, 6).toString(),
+              "\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08");
+
+        ////////////////////////////////////////////////////////////////////
+        check(new StringBuffer().append(ascii).replace(3, 6, "AB").toString(),
+              "abcABgh");
+        check(new StringBuffer().append(asciiMixed).replace(3, 6, "AB").toString(),
+              "abcABfgh");
+        check(new StringBuffer().append(bmp).replace(3, 6, "AB").toString(),
+              "\u4e00\u4e01\u4e02AB\u4e06\u4e07\u4e08");
+
+        check(new StringBuffer().append(bmpMixed).replace(3, 6, "").toString(),
+              "\u4e00\u4e01\u4e02\u4e06\u4e07\u4e08");
+
+        check(new StringBuffer().append(ascii).replace(3, 6, "\u4e01\u4e02").toString(),
+              "abc\u4e01\u4e02gh");
+
+        ////////////////////////////////////////////////////////////////////
+        check(new StringBuffer().append(ascii).insert(3, "").toString(),
+              "abcdefgh");
+        check(new StringBuffer().append(ascii).insert(3, "AB").toString(),
+              "abcABdefgh");
+        check(new StringBuffer().append(ascii).insert(3, "\u4e01\u4e02").toString(),
+              "abc\u4e01\u4e02defgh");
+
+        check(new StringBuffer().append(asciiMixed).insert(0, 'A').toString(),
+              "Aabc\u4e00\u4e01\u4e02fgh");
+        check(new StringBuffer().append(asciiMixed).insert(3, "A").toString(),
+              "abcA\u4e00\u4e01\u4e02fgh");
+
+        check(new StringBuffer().append(ascii).insert(3, 1234567).toString(),
+              "abc1234567defgh");
+        check(new StringBuffer().append(bmp).insert(3, 1234567).toString(),
+              "\u4e00\u4e01\u4e021234567\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08");
+
+        ////////////////////////////////////////////////////////////////////
+        check(new StringBuffer().append(ascii).append(1.23456).toString(),
+              "abcdefgh1.23456");
+        check(new StringBuffer().append(bmp).append(1.23456).toString(),
+              "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e081.23456");
+    }
+
+    private void checkGetChars(StringBuffer sb, int srcBegin, int srcEnd,
+            char expected[]) {
+        char[] dst = new char[srcEnd - srcBegin];
+        sb.getChars(srcBegin, srcEnd, dst, 0);
+        assertTrue(Arrays.equals(dst, expected));
+    }
+
+    private void checkSetCharAt(StringBuffer sb, int index, char ch,
+            String expected) {
+        sb.setCharAt(index, ch);
+        check(sb, expected);
+    }
+
+    private void checkSetLength(StringBuffer sb, int newLength, String expected) {
+        sb.setLength(newLength);
+        check(sb, expected);
+    }
+
+    private void check(StringBuffer sb, String expected) {
+        check(sb.toString(), expected);
+    }
+
+    private void check(String str, String expected) {
+        assertTrue(str.equals(expected), String.format(
+                "Get (%s) but expect (%s), ", escapeNonASCIIs(str),
+                escapeNonASCIIs(expected)));
+    }
+
+    /*
+     * Because right now system default charset in JPRT environment is only
+     * guaranteed to support ASCII characters in log, so we escape them.
+     */
+    private String escapeNonASCIIs(String str) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            if (c > 0x7F) {
+                sb.append("\\u").append(Integer.toHexString((int) c));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuffer/CompactStringBufferSerialization.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static jdk.testlibrary.SerializationUtils.*;
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug 8077559
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SerializationUtils
+ * @summary Tests Compact String. This one is testing StringBuffer serialization
+ *          among -XX:+CompactStrings/-XX:-CompactStrings/LegacyStringBuffer
+ * @run testng/othervm -XX:+CompactStrings CompactStringBufferSerialization
+ * @run testng/othervm -XX:-CompactStrings CompactStringBufferSerialization
+ */
+
+public class CompactStringBufferSerialization {
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                // every byte array is serialized from corresponding StringBuilder object
+                // by previous JDK(build 1.8.0_45-b14).
+                new Object[] {
+                        new StringBuffer(""),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 0, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("A"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 1, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("AB"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 2, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, 0, 65, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("abcdefghijk"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 11, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 27, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, 105, 0,
+                                106, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("\uff21"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 1, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, -1, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("\uff21\uff22"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 2, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, -1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("\uff21A\uff21A\uff21A\uff21A\uff21A"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 10, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 16, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, 0, 65, -1, 33, 0, 66, -1, 34, 0, 67, -1, 35, 0, 68, -1, 36, 0, 69, -1, 37,
+                                0, 70, -1, 38, 0, 71, -1, 39, 0, 72, -1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 16, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, -1, 33, 0, 65, -1, 34, 0, 66, -1, 35, 0, 67, -1, 36, 0, 68, -1, 37, 0, 69,
+                                -1, 38, 0, 70, -1, 39, 0, 71, -1, 40, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("\ud801\udc00\ud801\udc01\uff21A"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 6, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 22, -40, 1, -36, 0, -40, 1, -36, 1, -1, 33, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuffer("\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 22, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 102,
+                                102, 101, 114, 47, 7, 7, -39, -22, -56, -22, -45, 3, 0, 3, 73, 0, 5, 99, 111, 117, 110, 116, 90, 0, 6, 115, 104, 97, 114, 101,
+                                100, 91, 0, 5, 118, 97, 108, 117, 101, 116, 0, 2, 91, 67, 120, 112, 0, 0, 0, 10, 0, 117, 114, 0, 2, 91, 67, -80, 38, 102, -80,
+                                -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1,
+                                34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } } };
+    }
+
+    /*
+     * Verify serialization works between Compact StringBuffer/Legacy StringBuffer
+     */
+    @Test(dataProvider = "provider")
+    public void test(StringBuffer sbContent, byte[] baInJDK8) throws Exception {
+        // Serialize a StringBuffer object into byte array.
+        byte[] ba = serialize(sbContent);
+        assertEquals(ba, baInJDK8);
+        // Deserialize a StringBuffer object from byte array which is generated by previous JDK(build 1.8.0_45-b14).
+        Object obj = deserialize(ba);
+        assertEquals(obj.getClass(), StringBuffer.class);
+        assertTrue(equals((StringBuffer)obj, sbContent));
+    }
+
+    boolean equals(StringBuffer sb, StringBuffer expected) {
+        if(sb.length() == expected.length()
+                && sb.capacity() == expected.capacity()
+                && sb.toString().equals(expected.toString())) {
+            return true;
+        }
+        return false;
+    }
+}
--- a/jdk/test/java/lang/StringBuffer/Exceptions.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/StringBuffer/Exceptions.java	Wed Jul 05 21:00:20 2017 +0200
@@ -94,7 +94,7 @@
 
         System.out.println("StringBuffer.replace(int start, int end, String str)");
         tryCatch("  -1, 2, \" \"",
-                 new StringIndexOutOfBoundsException(-1),
+                 new StringIndexOutOfBoundsException("start -1, end 2, length 7"),
                  new Runnable() {
                 public void run() {
                     StringBuffer sb = new StringBuffer("hilbert");
@@ -102,14 +102,14 @@
                 }});
 
         tryCatch("  7, 8, \" \"",
-                 new StringIndexOutOfBoundsException("start > length()"),
+                 new StringIndexOutOfBoundsException("start 7, end 6, length 6"),
                  new Runnable() {
                 public void run() {
                     StringBuffer sb = new StringBuffer("banach");
                     sb.replace(7, 8, " ");
                 }});
         tryCatch("  2, 1, \" \"",
-                 new StringIndexOutOfBoundsException("start > end"),
+                 new StringIndexOutOfBoundsException("start 2, end 1, length 7"),
                  new Runnable() {
                 public void run() {
                     StringBuffer sb = new StringBuffer("riemann");
--- a/jdk/test/java/lang/StringBuilder/BuilderForwarding.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/StringBuilder/BuilderForwarding.java	Wed Jul 05 21:00:20 2017 +0200
@@ -264,4 +264,3 @@
         }
     }
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/CompactStringBuilder.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.Arrays;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8054307 8077559
+ * @summary Tests Compact String. This test is testing StringBuilder
+ *          behavior related to Compact String.
+ * @run testng/othervm -XX:+CompactStrings CompactStringBuilder
+ * @run testng/othervm -XX:-CompactStrings CompactStringBuilder
+ */
+
+public class CompactStringBuilder {
+
+    /*
+     * Tests for "A"
+     */
+    @Test
+    public void testCompactStringBuilderForLatinA() {
+        final String ORIGIN = "A";
+        /*
+         * Because right now ASCII is the default encoding parameter for source
+         * code in JDK build environment, so we escape them. same as below.
+         */
+        check(new StringBuilder(ORIGIN).append(new char[] { '\uFF21' }),
+                "A\uFF21");
+        check(new StringBuilder(ORIGIN).append(new StringBuffer("\uFF21")),
+                "A\uFF21");
+        check(new StringBuilder(ORIGIN).append("\uFF21"), "A\uFF21");
+        check(new StringBuilder(ORIGIN).append(new StringBuffer("\uFF21")),
+                "A\uFF21");
+        check(new StringBuilder(ORIGIN).delete(0, 1), "");
+        check(new StringBuilder(ORIGIN).delete(0, 0), "A");
+        check(new StringBuilder(ORIGIN).deleteCharAt(0), "");
+        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), 0);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), -1);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
+        assertEquals(new StringBuilder(ORIGIN).insert(1, "\uD801\uDC00")
+                .indexOf("A", 0), 0);
+        assertEquals(new StringBuilder(ORIGIN).insert(0, "\uD801\uDC00")
+                .indexOf("A", 0), 2);
+        check(new StringBuilder(ORIGIN).insert(0, new char[] {}), "A");
+        check(new StringBuilder(ORIGIN).insert(1, new char[] { '\uFF21' }),
+                "A\uFF21");
+        check(new StringBuilder(ORIGIN).insert(0, new char[] { '\uFF21' }),
+                "\uFF21A");
+        check(new StringBuilder(ORIGIN).insert(0, new StringBuffer("\uFF21")),
+                "\uFF21A");
+        check(new StringBuilder(ORIGIN).insert(1, new StringBuffer("\uFF21")),
+                "A\uFF21");
+        check(new StringBuilder(ORIGIN).insert(0, ""), "A");
+        check(new StringBuilder(ORIGIN).insert(0, "\uFF21"), "\uFF21A");
+        check(new StringBuilder(ORIGIN).insert(1, "\uFF21"), "A\uFF21");
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 0);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), -1);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 1);
+        check(new StringBuilder(ORIGIN).replace(0, 0, "\uFF21"), "\uFF21A");
+        check(new StringBuilder(ORIGIN).replace(0, 1, "\uFF21"), "\uFF21");
+        checkSetCharAt(new StringBuilder(ORIGIN), 0, '\uFF21', "\uFF21");
+        checkSetLength(new StringBuilder(ORIGIN), 0, "");
+        checkSetLength(new StringBuilder(ORIGIN), 1, "A");
+        check(new StringBuilder(ORIGIN).substring(0), "A");
+        check(new StringBuilder(ORIGIN).substring(1), "");
+    }
+
+    /*
+     * Tests for "\uFF21"
+     */
+    @Test
+    public void testCompactStringBuilderForNonLatinA() {
+        final String ORIGIN = "\uFF21";
+        check(new StringBuilder(ORIGIN).append(new char[] { 'A' }), "\uFF21A");
+        check(new StringBuilder(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
+        check(new StringBuilder(ORIGIN).append("A"), "\uFF21A");
+        check(new StringBuilder(ORIGIN).append(new StringBuffer("A")), "\uFF21A");
+        check(new StringBuilder(ORIGIN).delete(0, 1), "");
+        check(new StringBuilder(ORIGIN).delete(0, 0), "\uFF21");
+        check(new StringBuilder(ORIGIN).deleteCharAt(0), "");
+        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), -1);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), 0);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
+        check(new StringBuilder(ORIGIN).insert(0, new char[] {}), "\uFF21");
+        check(new StringBuilder(ORIGIN).insert(1, new char[] { 'A' }), "\uFF21A");
+        check(new StringBuilder(ORIGIN).insert(0, new char[] { 'A' }), "A\uFF21");
+        check(new StringBuilder(ORIGIN).insert(0, new StringBuffer("A")),
+                "A\uFF21");
+        check(new StringBuilder(ORIGIN).insert(1, new StringBuffer("A")),
+                "\uFF21A");
+        check(new StringBuilder(ORIGIN).insert(0, ""), "\uFF21");
+        check(new StringBuilder(ORIGIN).insert(0, "A"), "A\uFF21");
+        check(new StringBuilder(ORIGIN).insert(1, "A"), "\uFF21A");
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), -1);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 0);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 1);
+        check(new StringBuilder(ORIGIN).replace(0, 0, "A"), "A\uFF21");
+        check(new StringBuilder(ORIGIN).replace(0, 1, "A"), "A");
+        checkSetCharAt(new StringBuilder(ORIGIN), 0, 'A', "A");
+        checkSetLength(new StringBuilder(ORIGIN), 0, "");
+        checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
+        check(new StringBuilder(ORIGIN).substring(0), "\uFF21");
+        check(new StringBuilder(ORIGIN).substring(1), "");
+    }
+
+    /*
+     * Tests for "\uFF21A"
+     */
+    @Test
+    public void testCompactStringBuilderForMixedA1() {
+        final String ORIGIN = "\uFF21A";
+        check(new StringBuilder(ORIGIN).delete(0, 1), "A");
+        check(new StringBuilder(ORIGIN).delete(1, 2), "\uFF21");
+        check(new StringBuilder(ORIGIN).deleteCharAt(1), "\uFF21");
+        check(new StringBuilder(ORIGIN).deleteCharAt(0), "A");
+        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 0), 1);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 0), 0);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("", 0), 0);
+        check(new StringBuilder(ORIGIN).insert(1, new char[] { 'A' }),
+                "\uFF21AA");
+        check(new StringBuilder(ORIGIN).insert(0, new char[] { '\uFF21' }),
+                "\uFF21\uFF21A");
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 1);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 0);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 2);
+        check(new StringBuilder(ORIGIN).replace(0, 0, "A"), "A\uFF21A");
+        check(new StringBuilder(ORIGIN).replace(0, 1, "A"), "AA");
+        checkSetCharAt(new StringBuilder(ORIGIN), 0, 'A', "AA");
+        checkSetLength(new StringBuilder(ORIGIN), 0, "");
+        checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
+        check(new StringBuilder(ORIGIN).substring(0), "\uFF21A");
+        check(new StringBuilder(ORIGIN).substring(1), "A");
+    }
+
+    /*
+     * Tests for "A\uFF21"
+     */
+    @Test
+    public void testCompactStringBuilderForMixedA2() {
+        final String ORIGIN = "A\uFF21";
+        check(new StringBuilder(ORIGIN).replace(1, 2, "A"), "AA");
+        checkSetLength(new StringBuilder(ORIGIN), 1, "A");
+        check(new StringBuilder(ORIGIN).substring(0), "A\uFF21");
+        check(new StringBuilder(ORIGIN).substring(1), "\uFF21");
+        check(new StringBuilder(ORIGIN).substring(0, 1), "A");
+    }
+
+    /*
+     * Tests for "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A"
+     */
+    @Test
+    public void testCompactStringBuilderForDuplicatedMixedA1() {
+        final String ORIGIN = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A";
+        checkSetLength(new StringBuilder(ORIGIN), 1, "\uFF21");
+        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 5), 5);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 5), 6);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 9);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 8);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf(""), 10);
+        check(new StringBuilder(ORIGIN).substring(9), "A");
+        check(new StringBuilder(ORIGIN).substring(8), "\uFF21A");
+    }
+
+    /*
+     * Tests for "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21"
+     */
+    @Test
+    public void testCompactStringBuilderForDuplicatedMixedA2() {
+        final String ORIGIN = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21";
+        checkSetLength(new StringBuilder(ORIGIN), 1, "A");
+        assertEquals(new StringBuilder(ORIGIN).indexOf("A", 5), 6);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21", 5), 5);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 8);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 9);
+        check(new StringBuilder(ORIGIN).substring(9), "\uFF21");
+        check(new StringBuilder(ORIGIN).substring(8), "A\uFF21");
+    }
+
+    /*
+     * Tests for "\uD801\uDC00\uD801\uDC01"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePoint() {
+        final String ORIGIN = "\uD801\uDC00\uD801\uDC01";
+        check(new StringBuilder(ORIGIN).append("A"), "\uD801\uDC00\uD801\uDC01A");
+        check(new StringBuilder(ORIGIN).append("\uFF21"),
+                "\uD801\uDC00\uD801\uDC01\uFF21");
+        check(new StringBuilder(ORIGIN).appendCodePoint('A'),
+                "\uD801\uDC00\uD801\uDC01A");
+        check(new StringBuilder(ORIGIN).appendCodePoint('\uFF21'),
+                "\uD801\uDC00\uD801\uDC01\uFF21");
+        assertEquals(new StringBuilder(ORIGIN).charAt(0), '\uD801');
+        assertEquals(new StringBuilder(ORIGIN).codePointAt(0),
+                Character.codePointAt(ORIGIN, 0));
+        assertEquals(new StringBuilder(ORIGIN).codePointAt(1),
+                Character.codePointAt(ORIGIN, 1));
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2),
+                Character.codePointAt(ORIGIN, 0));
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
+        check(new StringBuilder(ORIGIN).delete(0, 2), "\uD801\uDC01");
+        check(new StringBuilder(ORIGIN).delete(0, 3), "\uDC01");
+        check(new StringBuilder(ORIGIN).deleteCharAt(1), "\uD801\uD801\uDC01");
+        checkGetChars(new StringBuilder(ORIGIN), 0, 3, new char[] { '\uD801',
+                '\uDC00', '\uD801' });
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uD801\uDC01"), 2);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uDC01"), 3);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21"), -1);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("A"), -1);
+        check(new StringBuilder(ORIGIN).insert(0, "\uFF21"),
+                "\uFF21\uD801\uDC00\uD801\uDC01");
+        check(new StringBuilder(ORIGIN).insert(1, "\uFF21"),
+                "\uD801\uFF21\uDC00\uD801\uDC01");
+        check(new StringBuilder(ORIGIN).insert(1, "A"),
+                "\uD801A\uDC00\uD801\uDC01");
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uDC00\uD801"), 1);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uD801"), 2);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), -1);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), -1);
+        assertEquals(new StringBuilder(ORIGIN).length(), 4);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 2);
+        check(new StringBuilder(ORIGIN).replace(0, 2, "A"), "A\uD801\uDC01");
+        check(new StringBuilder(ORIGIN).replace(0, 3, "A"), "A\uDC01");
+        check(new StringBuilder(ORIGIN).replace(0, 2, "\uFF21"),
+                "\uFF21\uD801\uDC01");
+        check(new StringBuilder(ORIGIN).replace(0, 3, "\uFF21"), "\uFF21\uDC01");
+        check(new StringBuilder(ORIGIN).reverse(), "\uD801\uDC01\uD801\uDC00");
+        checkSetCharAt(new StringBuilder(ORIGIN), 1, '\uDC01',
+                "\uD801\uDC01\uD801\uDC01");
+        checkSetCharAt(new StringBuilder(ORIGIN), 1, 'A', "\uD801A\uD801\uDC01");
+        checkSetLength(new StringBuilder(ORIGIN), 2, "\uD801\uDC00");
+        checkSetLength(new StringBuilder(ORIGIN), 3, "\uD801\uDC00\uD801");
+        check(new StringBuilder(ORIGIN).substring(1, 3), "\uDC00\uD801");
+    }
+
+    /*
+     * Tests for "A\uD801\uDC00\uFF21"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePointMixed1() {
+        final String ORIGIN = "A\uD801\uDC00\uFF21";
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(3),
+                Character.codePointAt(ORIGIN, 1));
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), '\uD801');
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), 'A');
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 2);
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 4), 3);
+        check(new StringBuilder(ORIGIN).delete(0, 1), "\uD801\uDC00\uFF21");
+        check(new StringBuilder(ORIGIN).delete(0, 1).delete(2, 3),
+                "\uD801\uDC00");
+        check(new StringBuilder(ORIGIN).deleteCharAt(3).deleteCharAt(0),
+                "\uD801\uDC00");
+        assertEquals(new StringBuilder(ORIGIN).indexOf("\uFF21"), 3);
+        assertEquals(new StringBuilder(ORIGIN).indexOf("A"), 0);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("\uFF21"), 3);
+        assertEquals(new StringBuilder(ORIGIN).lastIndexOf("A"), 0);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 3);
+        check(new StringBuilder(ORIGIN).replace(1, 3, "A"), "AA\uFF21");
+        check(new StringBuilder(ORIGIN).replace(1, 4, "A"), "AA");
+        check(new StringBuilder(ORIGIN).replace(1, 4, ""), "A");
+        check(new StringBuilder(ORIGIN).reverse(), "\uFF21\uD801\uDC00A");
+        checkSetLength(new StringBuilder(ORIGIN), 1, "A");
+        check(new StringBuilder(ORIGIN).substring(0, 1), "A");
+    }
+
+    /*
+     * Tests for "\uD801\uDC00\uFF21A"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePointMixed2() {
+        final String ORIGIN = "\uD801\uDC00\uFF21A";
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(3),
+                Character.codePointAt(ORIGIN, 2));
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2),
+                Character.codePointAt(ORIGIN, 0));
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), '\uD801');
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 2);
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 4), 3);
+        check(new StringBuilder(ORIGIN).delete(0, 2), "\uFF21A");
+        check(new StringBuilder(ORIGIN).delete(0, 3), "A");
+        check(new StringBuilder(ORIGIN).deleteCharAt(0).deleteCharAt(0)
+                .deleteCharAt(0), "A");
+        assertEquals(new StringBuilder(ORIGIN).indexOf("A"), 3);
+        assertEquals(new StringBuilder(ORIGIN).delete(0, 3).indexOf("A"), 0);
+        assertEquals(new StringBuilder(ORIGIN).replace(0, 3, "B").indexOf("A"),
+                1);
+        assertEquals(new StringBuilder(ORIGIN).substring(3, 4).indexOf("A"), 0);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 2);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
+        check(new StringBuilder(ORIGIN).replace(0, 3, "B"), "BA");
+        check(new StringBuilder(ORIGIN).reverse(), "A\uFF21\uD801\uDC00");
+    }
+
+    /*
+     * Tests for "\uD801A\uDC00\uFF21"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePointMixed3() {
+        final String ORIGIN = "\uD801A\uDC00\uFF21";
+        assertEquals(new StringBuilder(ORIGIN).codePointAt(1), 'A');
+        assertEquals(new StringBuilder(ORIGIN).codePointAt(3), '\uFF21');
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), '\uD801');
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), 'A');
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), '\uDC00');
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 3);
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
+        assertEquals(new StringBuilder(ORIGIN).delete(0, 1).delete(1, 3)
+                .indexOf("A"), 0);
+        assertEquals(
+                new StringBuilder(ORIGIN).replace(0, 1, "B").replace(2, 4, "C")
+                        .indexOf("A"), 1);
+        assertEquals(new StringBuilder(ORIGIN).substring(1, 4).substring(0, 1)
+                .indexOf("A"), 0);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
+        check(new StringBuilder(ORIGIN).reverse(), "\uFF21\uDC00A\uD801");
+    }
+
+    /*
+     * Tests for "A\uDC01\uFF21\uD801"
+     */
+    @Test
+    public void testCompactStringForSupplementaryCodePointMixed4() {
+        final String ORIGIN = "A\uDC01\uFF21\uD801";
+        assertEquals(new StringBuilder(ORIGIN).codePointAt(1), '\uDC01');
+        assertEquals(new StringBuilder(ORIGIN).codePointAt(3), '\uD801');
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(1), 'A');
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(2), '\uDC01');
+        assertEquals(new StringBuilder(ORIGIN).codePointBefore(3), '\uFF21');
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(0, 3), 3);
+        assertEquals(new StringBuilder(ORIGIN).codePointCount(1, 3), 2);
+        assertEquals(new StringBuilder(ORIGIN).delete(1, 4).indexOf("A"), 0);
+        assertEquals(new StringBuilder(ORIGIN).replace(1, 4, "B").indexOf("A"),
+                0);
+        assertEquals(new StringBuilder(ORIGIN).substring(0, 1).indexOf("A"), 0);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(0, 1), 1);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(1, 1), 2);
+        assertEquals(new StringBuilder(ORIGIN).offsetByCodePoints(2, 1), 3);
+        check(new StringBuilder(ORIGIN).reverse(), "\uD801\uFF21\uDC01A");
+    }
+
+    private void checkGetChars(StringBuilder sb, int srcBegin, int srcEnd,
+            char expected[]) {
+        char[] dst = new char[srcEnd - srcBegin];
+        sb.getChars(srcBegin, srcEnd, dst, 0);
+        assertTrue(Arrays.equals(dst, expected));
+    }
+
+    private void checkSetCharAt(StringBuilder sb, int index, char ch,
+            String expected) {
+        sb.setCharAt(index, ch);
+        check(sb, expected);
+    }
+
+    private void checkSetLength(StringBuilder sb, int newLength, String expected) {
+        sb.setLength(newLength);
+        check(sb, expected);
+    }
+
+    private void check(StringBuilder sb, String expected) {
+        check(sb.toString(), expected);
+    }
+
+    private void check(String str, String expected) {
+        assertTrue(str.equals(expected), String.format(
+                "Get (%s) but expect (%s), ", escapeNonASCIIs(str),
+                escapeNonASCIIs(expected)));
+    }
+
+    /*
+     * Because right now system default charset in JPRT environment is only
+     * guaranteed to support ASCII characters in log, so we escape them.
+     */
+    private String escapeNonASCIIs(String str) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            if (c > 0x7F) {
+                sb.append("\\u").append(Integer.toHexString((int) c));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StringBuilder/CompactStringBuilderSerialization.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static jdk.testlibrary.SerializationUtils.*;
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug 8077559
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SerializationUtils
+ * @summary Tests Compact String. This one is testing StringBuilder serialization
+ *          among -XX:+CompactStrings/-XX:-CompactStrings/LegacyStringBuilder
+ * @run testng/othervm -XX:+CompactStrings CompactStringBuilderSerialization
+ * @run testng/othervm -XX:-CompactStrings CompactStringBuilderSerialization
+ */
+
+public class CompactStringBuilderSerialization {
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                // every byte array is serialized from corresponding StringBuffer object
+                // by previous JDK(build 1.8.0_45-b14).
+                new Object[] {
+                        new StringBuilder(""),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 0, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("A"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 1, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("AB"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 2, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, 0, 65, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("abcdefghijk"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 11, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 27, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0,
+                                105, 0, 106, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("\uff21"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 1, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 17, -1, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("\uff21\uff22"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 2, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 18, -1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("\uff21A\uff21A\uff21A\uff21A\uff21A"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 10, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1, 33, 0, 65, -1,
+                                33, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("A\uff21B\uff22C\uff23D\uff24E\uff25F\uff26G\uff27H\uff28"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 16, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, 0, 65, -1, 33, 0, 66, -1, 34, 0, 67, -1, 35, 0, 68, -1, 36, 0,
+                                69, -1, 37, 0, 70, -1, 38, 0, 71, -1, 39, 0, 72, -1, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("\uff21A\uff22B\uff23C\uff24D\uff25E\uff26F\uff27G\uff28H"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 16, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 32, -1, 33, 0, 65, -1, 34, 0, 66, -1, 35, 0, 67, -1, 36, 0, 68, -1,
+                                37, 0, 69, -1, 38, 0, 70, -1, 39, 0, 71, -1, 40, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("\ud801\udc00\ud801\udc01\uff21A"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 6, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 22, -40, 1, -36, 0, -40, 1, -36, 1, -1, 33, 0, 65, 0, 0, 0, 0, 0, 0,
+                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } },
+                new Object[] {
+                        new StringBuilder("\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22\uff21\uff22"),
+                        new byte[] { -84, -19, 0, 5, 115, 114, 0, 23, 106, 97, 118, 97, 46, 108, 97, 110, 103, 46, 83, 116, 114, 105, 110, 103, 66, 117, 105,
+                                108, 100, 101, 114, 60, -43, -5, 20, 90, 76, 106, -53, 3, 0, 0, 120, 112, 119, 4, 0, 0, 0, 10, 117, 114, 0, 2, 91, 67, -80, 38,
+                                102, -80, -30, 93, -124, -84, 2, 0, 0, 120, 112, 0, 0, 0, 26, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34, -1, 33, -1, 34,
+                                -1, 33, -1, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120 } } };
+    }
+
+    /*
+     * Verify serialization works between Compact StringBuilder/Legacy StringBuilder
+     */
+    @Test(dataProvider = "provider")
+    public void test(StringBuilder sbContent, byte[] baInJDK8) throws Exception {
+        // Serialize a StringBuilder object into byte array.
+        byte[] ba = serialize(sbContent);
+        assertEquals(ba, baInJDK8);
+        // Deserialize a StringBuilder object from byte array which is generated by previous JDK(build 1.8.0_45-b14).
+        Object obj = deserialize(ba);
+        assertEquals(obj.getClass(), StringBuilder.class);
+        assertTrue(equals((StringBuilder)obj, sbContent));
+    }
+
+    boolean equals(StringBuilder sb, StringBuilder expected) {
+        if(sb.length() == expected.length()
+                && sb.capacity() == expected.capacity()
+                && sb.toString().equals(expected.toString())) {
+            return true;
+        }
+        return false;
+    }
+}
--- a/jdk/test/java/lang/StringBuilder/Exceptions.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/lang/StringBuilder/Exceptions.java	Wed Jul 05 21:00:20 2017 +0200
@@ -94,21 +94,21 @@
 
         System.out.println("StringBuilder.replace(int start, int end, String str)");
         tryCatch("  -1, 2, \" \"",
-                 new StringIndexOutOfBoundsException(-1),
+                 new StringIndexOutOfBoundsException("start -1, end 2, length 7"),
                  new Runnable() {
                 public void run() {
                     StringBuilder sb = new StringBuilder("hilbert");
                     sb.replace(-1, 2, " ");
                 }});
         tryCatch("  7, 8, \" \"",
-                 new StringIndexOutOfBoundsException("start > length()"),
+                 new StringIndexOutOfBoundsException("start 7, end 6, length 6"),
                  new Runnable() {
                 public void run() {
                     StringBuilder sb = new StringBuilder("banach");
                     sb.replace(7, 8, " ");
                 }});
         tryCatch("  2, 1, \" \"",
-                 new StringIndexOutOfBoundsException("start > end"),
+                 new StringIndexOutOfBoundsException("start 2, end 1, length 7"),
                  new Runnable() {
                 public void run() {
                     StringBuilder sb = new StringBuilder("riemann");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/SecureRandom/DefaultProvider.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import static java.lang.System.out;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+/**
+ * @test
+ * @bug 8048356
+ * @summary Assert default provider used on all OS for SecureRandom
+ */
+public class DefaultProvider {
+
+    private static final String OS_NAME = System.getProperty("os.name");
+    private static final String SUNOS = "SunOS";
+    private static final String WINDOWS = "Windows";
+
+    public static void main(String[] args) throws NoSuchAlgorithmException {
+        out.println("Operating System: " + OS_NAME);
+
+        /* Test default provider used with constructor */
+        out.println("TEST: Default provider with constructor");
+        SecureRandom secureRandom = new SecureRandom();
+        String provider = secureRandom.getProvider().getName();
+        if (OS_NAME.startsWith(SUNOS)) {
+            if (!provider.startsWith("SunPKCS11-")) {
+                throw new RuntimeException("Unexpected provider name: "
+                        + provider);
+            }
+        } else if (!provider.equals("SUN")) {
+            throw new RuntimeException("Unexpected provider name: "
+                    + provider);
+        }
+        out.println("Passed, default provider with constructor: " + provider);
+
+        /* Test default provider with getInstance(String algorithm) */
+        out.println("TEST: SHA1PRNG supported on all platforms by SUN provider");
+        String algorithm = "SHA1PRNG";
+        provider = "SUN";
+
+        SecureRandom instance = SecureRandom.getInstance(algorithm);
+        assertInstance(instance, algorithm, provider);
+        out.println("Passed.");
+
+        if (!OS_NAME.startsWith(WINDOWS)) {
+            out.println("TEST: NativePRNG supported on all platforms"
+                    + "(except Windows), by SUN provider");
+            algorithm = "NativePRNG";
+            provider = "SUN";
+        } else {
+            out.println(
+                    "TEST: Windows-PRNG supported on windows by SunMSCAPI provider");
+            algorithm = "Windows-PRNG";
+            provider = "SunMSCAPI";
+        }
+        instance = SecureRandom.getInstance(algorithm);
+        assertInstance(instance, algorithm, provider);
+        out.println("Passed.");
+
+        if (OS_NAME.startsWith(SUNOS)) {
+            out.println(
+                    "TEST: PKCS11 is supported on Solaris by SunPKCS11 provider");
+            algorithm = "PKCS11";
+            provider = "SunPKCS11-Solaris";
+            instance = SecureRandom.getInstance(algorithm);
+            assertInstance(instance, algorithm, provider);
+            out.println("Passed.");
+        }
+    }
+
+    private static void assertInstance(SecureRandom instance,
+            String expectedAlgorithm,
+            String expectedProvider) {
+        if (instance != null) {
+            if (!expectedAlgorithm.equalsIgnoreCase(instance.getAlgorithm())) {
+                throw new RuntimeException("Expected algorithm:"
+                        + expectedAlgorithm + " actual: " + instance.getAlgorithm());
+            }
+
+            if (!expectedProvider.equalsIgnoreCase(instance.getProvider().getName())) {
+                throw new RuntimeException("Expected provider: "
+                        + expectedProvider + " actual: "
+                        + instance.getProvider().getName());
+            }
+        } else {
+            throw new RuntimeException("Secure instance is not created");
+        }
+    }
+}
--- a/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java	Wed Jul 05 21:00:20 2017 +0200
@@ -156,6 +156,7 @@
                 {"UTC", 3, -1, ZoneId.of("UTC"), false},
                 {"UT", 2, -1, ZoneId.of("UT"), false},
                 {"GMT", 3, -1, ZoneId.of("GMT"), false},
+                {"GMT0", 4, -1, ZoneId.of("GMT0"), false},
 
                 {"+00:00", 6, -1, ZoneOffset.UTC, true},
                 {"UTC+00:00", 9, -1, ZoneId.of("UTC"), false},
--- a/jdk/test/java/time/test/java/time/temporal/TestIsoWeekFields.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/time/test/java/time/temporal/TestIsoWeekFields.java	Wed Jul 05 21:00:20 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014,2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -121,6 +121,14 @@
         assertEquals(IsoFields.WEEK_BASED_YEAR.isSupportedBy(ThaiBuddhistDate.now()), false);
     }
 
+    @Test
+    public void test_Unit_isSupportedBy_ISO() {
+        assertEquals(IsoFields.WEEK_BASED_YEARS.isSupportedBy(LocalDate.now()),true);
+        assertEquals(IsoFields.WEEK_BASED_YEARS.isSupportedBy(ThaiBuddhistDate.now()),false);
+        assertEquals(IsoFields.QUARTER_YEARS.isSupportedBy(LocalDate.now()),true);
+        assertEquals(IsoFields.QUARTER_YEARS.isSupportedBy(ThaiBuddhistDate.now()),false);
+    }
+
     @Test(dataProvider = "fields")
     public void test_WBY_range(TemporalField weekField, TemporalField yearField) {
         assertEquals(yearField.range(), ValueRange.of(Year.MIN_VALUE, Year.MAX_VALUE));
--- a/jdk/test/java/util/Objects/BasicObjectsTest.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/util/Objects/BasicObjectsTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -241,12 +241,12 @@
         String nonNullString = "non-null";
 
         // Confirm the compile time return type matches
-        String result = Objects.nonNullElse(nullString, defString);
+        String result = Objects.requireNonNullElse(nullString, defString);
         errors += (result == defString) ? 0 : 1;
-        errors += (Objects.nonNullElse(nonNullString, defString) == nonNullString) ? 0 : 1;
-        errors += (Objects.nonNullElse(nonNullString, null) == nonNullString) ? 0 : 1;
+        errors += (Objects.requireNonNullElse(nonNullString, defString) == nonNullString) ? 0 : 1;
+        errors += (Objects.requireNonNullElse(nonNullString, null) == nonNullString) ? 0 : 1;
         try {
-            Objects.nonNullElse(null, null);
+            Objects.requireNonNullElse(null, null);
             errors += 1;
         } catch (NullPointerException npe) {
             // expected
@@ -254,20 +254,20 @@
         }
 
 
-        // Test nonNullElseGet with a supplier
-        errors += (Objects.nonNullElseGet(nullString, () -> defString) == defString) ? 0 : 1;
-        errors += (Objects.nonNullElseGet(nonNullString, () -> defString) == nonNullString) ? 0 : 1;
-        errors += (Objects.nonNullElseGet(nonNullString, () -> null) == nonNullString) ? 0 : 1;
+        // Test requireNonNullElseGet with a supplier
+        errors += (Objects.requireNonNullElseGet(nullString, () -> defString) == defString) ? 0 : 1;
+        errors += (Objects.requireNonNullElseGet(nonNullString, () -> defString) == nonNullString) ? 0 : 1;
+        errors += (Objects.requireNonNullElseGet(nonNullString, () -> null) == nonNullString) ? 0 : 1;
 
         try {
-            Objects.nonNullElseGet(null, () -> null);
+            Objects.requireNonNullElseGet(null, () -> null);
             errors += 1;
         } catch (NullPointerException npe) {
             // expected
             errors += npe.getMessage().equals("supplier.get()") ? 0 : 1;
         }
         try {       // supplier is null
-            Objects.nonNullElseGet(null, null);
+            Objects.requireNonNullElseGet(null, null);
             errors += 1;
         } catch (NullPointerException npe) {
             // expected
--- a/jdk/test/java/util/concurrent/Phaser/Basic.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/util/concurrent/Phaser/Basic.java	Wed Jul 05 21:00:20 2017 +0200
@@ -34,6 +34,7 @@
 /*
  * @test
  * @bug 6445158
+ * @key intermittent
  * @summary Basic tests for Phaser
  * @author Chris Hegarty
  */
--- a/jdk/test/java/util/zip/TestLocalTime.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/java/util/zip/TestLocalTime.java	Wed Jul 05 21:00:20 2017 +0200
@@ -21,9 +21,10 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 8075526
+ * @key intermittent
  * @summary Test timestamp via ZipEntry.get/setTimeLocal()
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/SerializationUtils.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.testlibrary;
+
+import java.io.*;
+
+/**
+ * Common library for various test serialization utility functions.
+ */
+public final class SerializationUtils {
+    /*
+     * Serialize an object into byte array.
+     */
+    public static byte[] serialize(Object obj) throws Exception {
+        try (ByteArrayOutputStream bs = new ByteArrayOutputStream();
+                ObjectOutputStream out = new ObjectOutputStream(bs);) {
+            out.writeObject(obj);
+            return bs.toByteArray();
+        }
+    }
+
+    /*
+     * Deserialize an object from byte array.
+     */
+    public static Object deserialize(byte[] ba) throws Exception {
+        try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(ba));) {
+            return in.readObject();
+        }
+    }
+}
--- a/jdk/test/sun/nio/cs/TestStringCoding.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/sun/nio/cs/TestStringCoding.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 6636323 6636319 7040220 7096080 7183053 8080248
+ * @bug 6636323 6636319 7040220 7096080 7183053 8080248 8054307
  * @summary Test if StringCoding and NIO result have the same de/encoding result
  * @modules java.base/sun.nio.cs
  * @run main/othervm/timeout=2000 TestStringCoding
@@ -36,41 +36,61 @@
 public class TestStringCoding {
     public static void main(String[] args) throws Throwable {
 
+        // full bmp first
+        char[] bmp = new char[0x10000];
+        for (int i = 0; i < 0x10000; i++) {
+            bmp[i] = (char)i;
+        }
+        char[] latin = Arrays.copyOf(bmp, 0x100);
+        char[] ascii =  Arrays.copyOf(bmp, 0x80);
+
+        byte[] latinBA = new byte[0x100];
+        for (int i = 0; i < 0x100; i++) {
+            latinBA[i] = (byte)i;
+        }
+        byte[] asciiBA =  Arrays.copyOf(latinBA, 0x80);
+
         for (Boolean hasSM: new boolean[] { false, true }) {
-            if (hasSM)
+            if (hasSM) {
                 System.setSecurityManager(new PermissiveSecurityManger());
+            }
             for (Charset cs:  Charset.availableCharsets().values()) {
                 if ("ISO-2022-CN".equals(cs.name()) ||
                     "x-COMPOUND_TEXT".equals(cs.name()) ||
                     "x-JISAutoDetect".equals(cs.name()))
                     continue;
                 System.out.printf("Testing(sm=%b) " + cs.name() + "....", hasSM);
-                // full bmp first
-                char[] bmpCA = new char[0x10000];
-                for (int i = 0; i < 0x10000; i++) {
-                     bmpCA[i] = (char)i;
-                }
-                byte[] sbBA = new byte[0x100];
-                for (int i = 0; i < 0x100; i++) {
-                    sbBA[i] = (byte)i;
-                }
-                test(cs, bmpCA, sbBA);
+
+                testNewString(cs, testGetBytes(cs, new String(bmp)));
+                testNewString(cs, testGetBytes(cs, new String(latin)));
+                testNewString(cs, testGetBytes(cs, new String(ascii)));
+                testGetBytes(cs, testNewString(cs, latinBA));
+                testGetBytes(cs, testNewString(cs, asciiBA));
+
                 // "randomed" sizes
                 Random rnd = new Random();
                 for (int i = 0; i < 10; i++) {
-                    int clen = rnd.nextInt(0x10000);
-                    int blen = rnd.nextInt(0x100);
                     //System.out.printf("    blen=%d, clen=%d%n", blen, clen);
-                    test(cs, Arrays.copyOf(bmpCA, clen), Arrays.copyOf(sbBA, blen));
+                    char[] bmp0 = Arrays.copyOf(bmp, rnd.nextInt(0x10000));
+                    testNewString(cs, testGetBytes(cs, new String(bmp0)));
                     //add a pair of surrogates
-                    int pos = clen / 2;
-                    if ((pos + 1) < blen) {
-                        bmpCA[pos] = '\uD800';
-                        bmpCA[pos+1] = '\uDC00';
+                    int pos = bmp0.length / 2;
+                    if ((pos + 1) < bmp0.length) {
+                        bmp0[pos] = '\uD800';
+                        bmp0[pos+1] = '\uDC00';
                     }
-                    test(cs, Arrays.copyOf(bmpCA, clen), Arrays.copyOf(sbBA, blen));
+                    testNewString(cs, testGetBytes(cs, new String(bmp0)));
+
+                    char[] latin0 = Arrays.copyOf(latin, rnd.nextInt(0x100));
+                    char[] ascii0 = Arrays.copyOf(ascii, rnd.nextInt(0x80));
+                    byte[] latinBA0 = Arrays.copyOf(latinBA, rnd.nextInt(0x100));
+                    byte[] asciiBA0 = Arrays.copyOf(asciiBA, rnd.nextInt(0x80));
+                    testNewString(cs, testGetBytes(cs, new String(latin0)));
+                    testNewString(cs, testGetBytes(cs, new String(ascii0)));
+                    testGetBytes(cs, testNewString(cs, latinBA0));
+                    testGetBytes(cs, testNewString(cs, asciiBA0));
                 }
-
+                testSurrogates(cs);
                 testMixed(cs);
                 System.out.println("done!");
             }
@@ -109,8 +129,9 @@
 
         //getBytes(cs);
         bmpBA = bmpStr.getBytes(cs);
-        if (!Arrays.equals(bmpBA, baNIO))
+        if (!Arrays.equals(bmpBA, baNIO)) {
             throw new RuntimeException("getBytes(cs) failed  -> " + cs.name());
+        }
 
         //new String(csn);
         String strSC = new String(bmpBA, cs.name());
@@ -118,49 +139,61 @@
         if(!strNIO.equals(strSC)) {
             throw new RuntimeException("new String(csn) failed  -> " + cs.name());
         }
-
         //new String(cs);
         strSC = new String(bmpBA, cs);
-        if (!strNIO.equals(strSC))
+        if (!strNIO.equals(strSC)) {
             throw new RuntimeException("new String(cs) failed  -> " + cs.name());
-
+        }
     }
 
-    static void test(Charset cs, char[] bmpCA, byte[] sbBA) throws Throwable {
-        String bmpStr = new String(bmpCA);
-        CharsetDecoder dec = cs.newDecoder()
-            .onMalformedInput(CodingErrorAction.REPLACE)
-            .onUnmappableCharacter(CodingErrorAction.REPLACE);
+    static byte[] getBytes(CharsetEncoder enc, String str) throws Throwable {
+        ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(str.toCharArray()));
+        byte[] ba = new byte[bf.limit()];
+        bf.get(ba, 0, ba.length);
+        return ba;
+    }
+
+    static byte[] testGetBytes(Charset cs, String str) throws Throwable {
         CharsetEncoder enc = cs.newEncoder()
             .onMalformedInput(CodingErrorAction.REPLACE)
             .onUnmappableCharacter(CodingErrorAction.REPLACE);
-
         //getBytes(csn);
-        byte[] baSC = bmpStr.getBytes(cs.name());
-        ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(bmpCA));
-        byte[] baNIO = new byte[bf.limit()];
-        bf.get(baNIO, 0, baNIO.length);
-        if (!Arrays.equals(baSC, baNIO))
+        byte[] baSC = str.getBytes(cs.name());
+        byte[] baNIO = getBytes(enc, str);
+        if (!Arrays.equals(baSC, baNIO)) {
             throw new RuntimeException("getBytes(csn) failed  -> " + cs.name());
-
+        }
         //getBytes(cs);
-        baSC = bmpStr.getBytes(cs);
-        if (!Arrays.equals(baSC, baNIO))
+        baSC = str.getBytes(cs);
+        if (!Arrays.equals(baSC, baNIO)) {
             throw new RuntimeException("getBytes(cs) failed  -> " + cs.name());
+        }
+        return baSC;
+    }
 
+    static String testNewString(Charset cs, byte[] ba) throws Throwable {
+        CharsetDecoder dec = cs.newDecoder()
+            .onMalformedInput(CodingErrorAction.REPLACE)
+            .onUnmappableCharacter(CodingErrorAction.REPLACE);
         //new String(csn);
-        String strSC = new String(sbBA, cs.name());
-        String strNIO = dec.reset().decode(ByteBuffer.wrap(sbBA)).toString();
-
-        if(!strNIO.equals(strSC))
+        String strSC = new String(ba, cs.name());
+        String strNIO = dec.reset().decode(ByteBuffer.wrap(ba)).toString();
+        if(!strNIO.equals(strSC)) {
             throw new RuntimeException("new String(csn) failed  -> " + cs.name());
+        }
+        //new String(cs);
+        strSC = new String(ba, cs);
+        if (!strNIO.equals(strSC)) {
+            throw new RuntimeException("new String(cs)/bmp failed  -> " + cs.name());
+        }
+        return strSC;
+    }
 
-        //new String(cs);
-        strSC = new String(sbBA, cs);
-        if (!strNIO.equals(strSC))
-            throw new RuntimeException("new String(cs) failed  -> " + cs.name());
-
+    static void testSurrogates(Charset cs) throws Throwable {
         //encode unmappable surrogates
+        CharsetEncoder enc = cs.newEncoder()
+            .onMalformedInput(CodingErrorAction.REPLACE)
+            .onUnmappableCharacter(CodingErrorAction.REPLACE);
         if (enc instanceof sun.nio.cs.ArrayEncoder &&
             cs.contains(Charset.forName("ASCII"))) {
             if (cs.name().equals("UTF-8") ||     // utf8 handles surrogates
--- a/jdk/test/sun/nio/cs/TestStringCodingUTF8.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/jdk/test/sun/nio/cs/TestStringCodingUTF8.java	Wed Jul 05 21:00:20 2017 +0200
@@ -22,7 +22,7 @@
  */
 
 /* @test
-   @bug 7040220
+   @bug 7040220 8054307
    @summary Test if StringCoding and NIO result have the same de/encoding result for UTF-8
  * @run main/othervm/timeout=2000 TestStringCodingUTF8
  * @key randomness
@@ -50,6 +50,18 @@
         }
         test(cs, bmp, 0, bmp.length);
 
+        char[] ascii = new char[0x80];
+        for (int i = 0; i < 0x80; i++) {
+            ascii[i] = (char)i;
+        }
+        test(cs, ascii, 0, ascii.length);
+
+        char[] latin1 = new char[0x100];
+        for (int i = 0; i < 0x100; i++) {
+            latin1[i] = (char)i;
+        }
+        test(cs, latin1, 0, latin1.length);
+
         ArrayList<Integer> list = new ArrayList<>(0x20000);
         for (int i = 0; i < 0x20000; i++) {
             list.add(i, i);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/jca/PreferredProviderNegativeTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8076359 8133151
+ * @summary Test for jdk.security.provider.preferred security property
+ * @requires os.name == "SunOS"
+ * @run main/othervm  PreferredProviderNegativeTest preJCESet AES:OracleUcrypto false
+ * @run main/othervm  PreferredProviderNegativeTest preJCESet AES:SunNegative true
+ * @run main/othervm  PreferredProviderNegativeTest afterJCESet AES:SunJGSS
+ * @run main/othervm  PreferredProviderNegativeTest afterJCESet AES:SunECNegative
+ * @run main/othervm  PreferredProviderNegativeTest invalidAlg AESNegative:SunJCE
+ */
+
+import java.security.Security;
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+
+public class PreferredProviderNegativeTest {
+
+    /*
+     * Test security property could be set by valid and invalid provider
+     * before JCE was loaded
+     */
+    public static void preJCESet(String value, boolean negativeProvider)
+            throws NoSuchAlgorithmException, NoSuchPaddingException {
+        Security.setProperty("jdk.security.provider.preferred", value);
+
+        if (!Security.getProperty("jdk.security.provider.preferred")
+                .equals(value)) {
+            throw new RuntimeException(
+                    "Test Failed:The property wasn't set");
+        }
+
+        String[] arrays = value.split(":");
+        Cipher cipher = Cipher.getInstance(arrays[0]);
+
+        if (negativeProvider) {
+            if (cipher.getProvider().getName().equals(arrays[1])) {
+                throw new RuntimeException(
+                        "Test Failed:The provider shouldn't be set");
+            }
+        } else {
+            if (!cipher.getProvider().getName().equals(arrays[1])) {
+                throw new RuntimeException(
+                        "Test Faild:The provider could be set "
+                                + "by valid provider ");
+            }
+        }
+        System.out.println("Test Pass");
+    }
+
+    /*
+     * Test that the setting of the security property after Cipher.getInstance()
+     * does not influence previously loaded instances
+     */
+    public static void afterJCESet(String value)
+            throws NoSuchAlgorithmException, NoSuchPaddingException {
+        String[] arrays = value.split(":");
+        Cipher cipher = Cipher.getInstance(arrays[0]);
+
+        Security.setProperty("jdk.security.provider.preferred", value);
+        if (!cipher.getProvider().getName().equals("SunJCE")) {
+            throw new RuntimeException(
+                    "Test Failed:The security property can't be updated after JCE load.");
+        }
+        System.out.println("Test Pass");
+    }
+
+    /* Test the security property with negative algorithm */
+    public static void invalidAlg(String value) throws NoSuchPaddingException {
+        String[] arrays = value.split(":");
+
+        try {
+            Security.setProperty("jdk.security.provider.preferred", value);
+            Cipher.getInstance(arrays[0]);
+        } catch (NoSuchAlgorithmException e) {
+            System.out.println("Test Pass:Got NoSuchAlgorithmException as expired");
+            return;
+        }
+        throw new RuntimeException(
+                "Test Failed:Expected NoSuchAlgorithmException was not thrown");
+    }
+
+    public static void main(String[] args)
+            throws NoSuchAlgorithmException, NoSuchPaddingException {
+        boolean negativeProvider;
+
+        if (args.length >= 2) {
+            switch (args[0]) {
+                case "preJCESet":
+                    negativeProvider = Boolean.valueOf(args[2]);
+                    PreferredProviderNegativeTest.preJCESet(args[1], negativeProvider);
+                    break;
+                case "afterJCESet":
+                    PreferredProviderNegativeTest.afterJCESet(args[1]);
+                    break;
+                case "invalidAlg":
+                    PreferredProviderNegativeTest.invalidAlg(args[1]);
+                    break;
+            }
+        } else {
+            throw new RuntimeException(
+                    "Test Failed:Please pass the correct args");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/jca/PreferredProviderTest.java	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8076359 8133151
+ * @summary Test the value for new jdk.security.provider.preferred security property
+ * @requires os.name == "SunOS"
+ */
+
+import java.security.KeyFactory;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.List;
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+
+public class PreferredProviderTest {
+
+    private static final List<DataTuple> SPARC_DATA = Arrays.asList(
+            new DataTuple("SHA-256", "SUN"), new DataTuple("SHA-384", "SUN"),
+            new DataTuple("SHA-512", "SUN"));
+    private static final List<DataTuple> X86_DATA = Arrays
+            .asList(new DataTuple("RSA", "SunRsaSign"));
+
+    public void RunTest(String type)
+            throws NoSuchAlgorithmException, NoSuchPaddingException {
+        String preferredProvider = Security
+                .getProperty("jdk.security.provider.preferred");
+        String actualProvider = null;
+        if (type.equals("sparcv9")) {
+            if (!preferredProvider.equals(
+                    "AES:SunJCE, SHA-256:SUN, SHA-384:SUN, SHA-512:SUN")) {
+                throw new RuntimeException(
+                        "Test Failed: wrong jdk.security.provider.preferred "
+                                + "value on solaris-sparcv9");
+            }
+            for (DataTuple dataTuple : SPARC_DATA) {
+                MessageDigest md = MessageDigest
+                        .getInstance(dataTuple.algorithm);
+                actualProvider = md.getProvider().getName();
+                if (!actualProvider.equals(dataTuple.provider)) {
+                    throw new RuntimeException(String.format(
+                            "Test Failed:Got wrong "
+                                    + "provider from Solaris-sparcv9 platform,"
+                                    + "Expected Provider: %s, Returned Provider: %s",
+                            dataTuple.provider, actualProvider));
+                }
+            }
+        } else if (type.equals("amd64")) {
+            if (!preferredProvider.equals("AES:SunJCE, RSA:SunRsaSign")) {
+                throw new RuntimeException(
+                        "Test Failed: wrong jdk.security.provider.preferred "
+                                + "value on solaris-x86");
+            }
+            for (DataTuple dataTuple : X86_DATA) {
+                KeyFactory keyFactory = KeyFactory
+                        .getInstance(dataTuple.algorithm);
+                actualProvider = keyFactory.getProvider().getName();
+                if (!actualProvider.equals(dataTuple.provider)) {
+                    throw new RuntimeException(String.format(
+                            "Test Failed:Got wrong "
+                                    + "provider from Solaris-x86 platform,"
+                                    + "Expected Provider: %s, Returned Provider: %s",
+                            dataTuple.provider, actualProvider));
+                }
+            }
+        } else {
+            throw new RuntimeException("Test Failed: wrong platform value");
+        }
+
+        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+        actualProvider = cipher.getProvider().getName();
+        if (!actualProvider.equals("SunJCE")) {
+            throw new RuntimeException(String.format(
+                    "Test Failed:Got wrong provider from Solaris-%s platform, "
+                            + "Expected Provider: SunJCE, Returned Provider: %s",
+                    type, actualProvider));
+        }
+
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        actualProvider = md.getProvider().getName();
+        if (!actualProvider.equals("OracleUcrypto")) {
+            throw new RuntimeException(String.format(
+                    "Test Failed:Got wrong provider from Solaris-%s platform,"
+                            + "Expected Provider: OracleUcrypto, Returned Provider: %s",
+                    type, actualProvider));
+        }
+    }
+
+    private static class DataTuple {
+        private final String provider;
+        private final String algorithm;
+
+        private DataTuple(String algorithm, String provider) {
+            this.algorithm = algorithm;
+            this.provider = provider;
+        }
+    }
+
+    public static void main(String[] args)
+            throws NoSuchAlgorithmException, NoSuchPaddingException {
+
+        String arch = System.getProperty("os.arch");
+        PreferredProviderTest pp = new PreferredProviderTest();
+        pp.RunTest(arch);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/BuildStatic.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+
+################################################################################
+#
+# Concatenate exported.symbols files for modules into a single global file.
+#
+
+GLOBAL_SYMBOLS_FILE := $(SUPPORT_OUTPUTDIR)/build-static/exported.symbols
+
+EXPORTED_SYMBOLS_MODULES := java.base jdk.jdwp.agent
+
+MODULES_SYMBOLS_FILES := $(foreach module, $(EXPORTED_SYMBOLS_MODULES), \
+    $(SUPPORT_OUTPUTDIR)/modules_libs/$(module)/$(module).symbols)
+
+$(GLOBAL_SYMBOLS_FILE): $(MODULES_SYMBOLS_FILES)
+	$(ECHO) $(LOG_INFO) "Generating global exported.symbols file"
+	$(MKDIR) -p $(@D)
+	$(CAT) $^ > $@
+
+TARGETS += $(GLOBAL_SYMBOLS_FILE)
+
+################################################################################
+
+all: $(TARGETS)
+
+.PHONY: default all
--- a/make/Init.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/make/Init.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -305,49 +305,20 @@
         endif
 
     on-failure:
-        ifneq ($(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*), )
-	  $(PRINTF) "=== Output from failing command(s) repeated here ===\n"
-	  $(foreach logfile, $(sort $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*)), \
-	      $(PRINTF) "* For target $(notdir $(basename $(logfile))):\n" $(NEWLINE) \
-	      $(CAT) $(logfile) | $(GREP) -v -e "^Note: including file:" $(NEWLINE) \
-	  )
-	  $(PRINTF) "=== End of repeated output ===\n"
+	$(call PrintFailureReports)
+	$(call PrintBuildLogFailures)
+	$(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors.\n\n"
+        ifneq ($(COMPARE_BUILD), )
+	  $(call CleanupCompareBuild)
         endif
-	if $(GREP) -q "recipe for target .* failed" $(BUILD_LOG) 2> /dev/null; then  \
-	  $(PRINTF) "=== Make failure sequence repeated here ===\n" ; \
-	  $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \
-	  $(PRINTF) "=== End of repeated output ===\n" ; \
-	  $(PRINTF) "Hint: Try searching the build log for the name of the first failed target.\n" ; \
-	else \
-	  $(PRINTF) "No indication of failed target found.\n" ; \
-	  $(PRINTF) "Hint: Try searching the build log for '] Error'.\n" ; \
-	fi
-	$(PRINTF) "Hint: If caused by a warning, try configure --disable-warnings-as-errors.\n\n"
 
     # Support targets for COMPARE_BUILD, used for makefile development
     pre-compare-build:
-	$(ECHO) "Preparing for comparison rebuild"
-        # Apply patch, if any
-        ifneq ($(COMPARE_BUILD_PATCH), )
-	  $(PATCH) -p1 < $(COMPARE_BUILD_PATCH)
-        endif
-        # Move the first build away and re-create the output directory
-	( cd $(TOPDIR) && \
-	    $(MV) $(OUTPUT_ROOT) $(OUTPUT_ROOT).OLD && \
-	    $(MKDIR) -p $(OUTPUT_ROOT) )
-        # Re-run configure with the same arguments (and possibly some additional),
-	# must be done after patching.
-	( cd $(OUTPUT_ROOT) && PATH="$(ORIGINAL_PATH)" \
-	    $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF))
+	$(call PrepareCompareBuild)
 
     post-compare-build:
-        # Compare first and second build. Ignore any error code from compare.sh.
-	$(ECHO) "Comparing between comparison rebuild (this/new) and baseline (other/old)"
-        ifneq ($(COMPARE_BUILD_COMP_DIR), )
-	  +(cd $(OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) -2dirs $(OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) $(OUTPUT_ROOT).OLD/$(COMPARE_BUILD_COMP_DIR) || true)
-        else
-	  +(cd $(OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) -o $(OUTPUT_ROOT).OLD || true)
-        endif
+	$(call CleanupCompareBuild)
+	$(call CompareBuildDoComparison)
 
   .PHONY: print-targets print-modules reconfigure main on-failure
 endif
--- a/make/InitSupport.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/make/InitSupport.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -321,6 +321,8 @@
   # If any value contains "+", it will be replaced by space.
   define ParseCompareBuild
     ifneq ($$(COMPARE_BUILD), )
+      COMPARE_BUILD_OUTPUT_ROOT := $(TOPDIR)/build/compare-build/$(CONF_NAME)
+
       ifneq ($$(findstring :, $$(COMPARE_BUILD)), )
         $$(foreach part, $$(subst :, , $$(COMPARE_BUILD)), \
           $$(if $$(filter PATCH=%, $$(part)), \
@@ -364,6 +366,73 @@
     endif
   endef
 
+  # Prepare for a comparison rebuild
+  define PrepareCompareBuild
+	$(ECHO) "Preparing for comparison rebuild"
+        # Apply patch, if any
+	$(if $(COMPARE_BUILD_PATCH), $(PATCH) -p1 < $(COMPARE_BUILD_PATCH))
+        # Move the first build away temporarily
+	$(RM) -r $(TOPDIR)/build/.compare-build-temp
+	$(MKDIR) -p $(TOPDIR)/build/.compare-build-temp
+	$(MV) $(OUTPUT_ROOT) $(TOPDIR)/build/.compare-build-temp
+        # Restore an old compare-build, or create a new compare-build directory.
+	if test -d $(COMPARE_BUILD_OUTPUT_ROOT); then \
+	  $(MV) $(COMPARE_BUILD_OUTPUT_ROOT) $(OUTPUT_ROOT); \
+	else \
+	  $(MKDIR) -p $(OUTPUT_ROOT); \
+	fi
+        # Re-run configure with the same arguments (and possibly some additional),
+        # must be done after patching.
+	( cd $(OUTPUT_ROOT) && PATH="$(ORIGINAL_PATH)" \
+	    $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF))
+  endef
+
+  # Cleanup after a compare build
+  define CleanupCompareBuild
+        # If running with a COMPARE_BUILD patch, reverse-apply it
+	$(if $(COMPARE_BUILD_PATCH), $(PATCH) -R -p1 < $(COMPARE_BUILD_PATCH))
+        # Move this build away and restore the original build
+	$(MKDIR) -p $(TOPDIR)/build/compare-build
+	$(MV) $(OUTPUT_ROOT) $(COMPARE_BUILD_OUTPUT_ROOT)
+	$(MV) $(TOPDIR)/build/.compare-build-temp/$(CONF_NAME) $(OUTPUT_ROOT)
+	$(RM) -r $(TOPDIR)/build/.compare-build-temp
+  endef
+
+  # Do the actual comparison of two builds
+  define CompareBuildDoComparison
+        # Compare first and second build. Ignore any error code from compare.sh.
+	$(ECHO) "Comparing between comparison rebuild (this/new) and baseline (other/old)"
+	$(if $(COMPARE_BUILD_COMP_DIR), \
+	  +(cd $(COMPARE_BUILD_OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) \
+	      -2dirs $(COMPARE_BUILD_OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) $(OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) || true), \
+	  +(cd $(COMPARE_BUILD_OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) \
+	      -o $(OUTPUT_ROOT) || true) \
+	)
+  endef
+
+  define PrintFailureReports
+	$(if $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*), \
+	  $(PRINTF) "=== Output from failing command(s) repeated here ===\n" $(NEWLINE) \
+	  $(foreach logfile, $(sort $(wildcard $(MAKESUPPORT_OUTPUTDIR)/failure-logs/*)), \
+	      $(PRINTF) "* For target $(notdir $(basename $(logfile))):\n" $(NEWLINE) \
+	      $(CAT) $(logfile) | $(GREP) -v -e "^Note: including file:" $(NEWLINE) \
+	  ) \
+	  $(PRINTF) "=== End of repeated output ===\n" \
+	)
+  endef
+
+  define PrintBuildLogFailures
+	if $(GREP) -q "recipe for target .* failed" $(BUILD_LOG) 2> /dev/null; then  \
+	  $(PRINTF) "=== Make failure sequence repeated here ===\n" ; \
+	  $(GREP) "recipe for target .* failed" $(BUILD_LOG) ; \
+	  $(PRINTF) "=== End of repeated output ===\n" ; \
+	  $(PRINTF) "Hint: Try searching the build log for the name of the first failed target.\n" ; \
+	else \
+	  $(PRINTF) "No indication of failed target found.\n" ; \
+	  $(PRINTF) "Hint: Try searching the build log for '] Error'.\n" ; \
+	fi
+  endef
+
   define RotateLogFiles
 	$(RM) $(BUILD_LOG).old 2> /dev/null
 	$(MV) $(BUILD_LOG) $(BUILD_LOG).old 2> /dev/null || true
--- a/make/Main.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/make/Main.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -93,7 +93,10 @@
 unpack-sec:
 	+($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f UnpackSecurity.gmk)
 
-ALL_TARGETS += import-hotspot unpack-sec
+generate-exported-symbols:
+	+($(CD) $(TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f BuildStatic.gmk)
+
+ALL_TARGETS += import-hotspot unpack-sec generate-exported-symbols
 
 ################################################################################
 # Gensrc targets, generating source before java compilation can be done
@@ -298,16 +301,23 @@
 test:
 	$(call RunTests, $(TEST))
 
+test-hotspot-jtreg:
+	$(call RunTests, "hotspot_all")
+
 test-hotspot-jtreg-native:
 	$(call RunTests, "hotspot_native_sanity")
 
+test-hotspot-internal:
+	$(call RunTests, "hotspot_internal")
+
 test-jdk-jtreg-native:
 	$(call RunTests, "jdk_native_sanity")
 
 test-make:
 	($(CD) $(SRC_ROOT)/test/make && $(MAKE) $(MAKE_ARGS) -f TestMake.gmk $(TEST_TARGET))
 
-ALL_TARGETS += test test-hotspot-jtreg-native test-jdk-jtreg-native test-make
+ALL_TARGETS += test test-hotspot-jtreg test-hotspot-jtreg-native \
+    test-hotspot-internal test-jdk-jtreg-native test-make
 
 ################################################################################
 # Verification targets
@@ -368,10 +378,16 @@
 
   import-hotspot: hotspot
 
+  generate-exported-symbols: java.base-libs jdk.jdwp.agent-libs
+
   $(LIBS_TARGETS): import-hotspot
 
   $(LAUNCHER_TARGETS): java.base-libs
 
+  ifeq ($(STATIC_BUILD), true)
+    $(LAUNCHER_TARGETS): generate-exported-symbols
+  endif
+
   # The demos are currently linking to libjvm and libjava, just like all other
   # jdk libs, even though they don't need to. To avoid warnings, make sure they
   # aren't built until after libjava and libjvm are available to link to.
@@ -462,6 +478,10 @@
 
   test-image-jdk-jtreg-native: build-test-jdk-jtreg-native
 
+  test-hotspot-internal: exploded-image
+
+  test-hotspot-jtreg: jimages test-image
+
 endif
 
 ################################################################################
--- a/make/common/NativeCompilation.gmk	Thu Nov 12 18:27:55 2015 -0800
+++ b/make/common/NativeCompilation.gmk	Wed Jul 05 21:00:20 2017 +0200
@@ -35,6 +35,31 @@
 endif
 
 ################################################################################
+# Create exported symbols file for static libraries
+################################################################################
+
+# get the exported symbols from mapfiles and if there
+# is no mapfile, get them from the archive
+define GetSymbols
+  $(RM) $$(@D)/$$(basename $$(@F)).symbols; \
+  if [ ! -z $$($1_MAPFILE) -a -e $$($1_MAPFILE) ]; then \
+    $(ECHO) "Getting symbols from mapfile $$($1_MAPFILE)"; \
+    $(AWK) '/global:/','/local:/' $$($1_MAPFILE) | \
+        $(SED) -e 's/#.*//;s/global://;s/local://;s/\;//;s/^[ 	]*/_/;/^_$$$$/d' | \
+        $(EGREP) -v "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" > \
+        $$(@D)/$$(basename $$(@F)).symbols || true; \
+    $(NM) $$($1_TARGET) | $(GREP)  " T " | \
+        $(EGREP) "JNI_OnLoad|JNI_OnUnload|Agent_OnLoad|Agent_OnUnload|Agent_OnAttach" | \
+        $(CUT) -d ' ' -f 3 >>  $$(@D)/$$(basename $$(@F)).symbols || true;\
+  else \
+    $(ECHO) "Getting symbols from nm"; \
+    $(NM) -m $$($1_TARGET) | $(GREP)  "__TEXT" | \
+        $(EGREP) -v "non-external|private extern|__TEXT,__eh_frame" | \
+        $(SED) -e  's/.* //' > $$(@D)/$$(basename $$(@F)).symbols; \
+  fi
+endef
+
+################################################################################
 # Define a native toolchain configuration that can be used by
 # SetupNativeCompilation calls
 #
@@ -274,6 +299,15 @@
 SetupNativeCompilation = $(NamedParamsMacroTemplate)
 define SetupNativeCompilationBody
 
+  # If we're doing a static build and producing a library
+  # force it to be a static library and remove the -l libraries
+  ifeq ($(STATIC_BUILD), true)
+    ifneq ($$($1_LIBRARY),)
+      $1_STATIC_LIBRARY := $$($1_LIBRARY)
+      $1_LIBRARY :=
+    endif
+  endif
+
   ifneq (,$$($1_BIN))
     $$(error BIN has been replaced with OBJECT_DIR)
   endif
@@ -495,6 +529,12 @@
     $1_EXTRA_CXXFLAGS += $$(CXX_FLAG_REORDER)
   endif
 
+  # Pass the library name for static JNI library naming
+  ifneq ($$($1_STATIC_LIBRARY),)
+    $1_EXTRA_CFLAGS += -DLIBRARY_NAME=$$($1_STATIC_LIBRARY)
+    $1_EXTRA_CXXFLAGS += -DLIBRARY_NAME=$$($1_STATIC_LIBRARY)
+  endif
+
   # Pick up disabled warnings, if possible on this platform.
   ifneq ($(DISABLE_WARNING_PREFIX),)
     $1_EXTRA_CFLAGS += $$(addprefix $(DISABLE_WARNING_PREFIX), $$($1_DISABLED_WARNINGS_$(TOOLCHAIN_TYPE)))
@@ -725,7 +765,10 @@
 	$(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)"
 	$(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \
 	    $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \
-	        $$($1_RES) $$($1_LIBS) $$($1_EXTRA_LIBS))
+	        $$($1_RES))
+        ifeq ($(STATIC_BUILD), true)
+	  $(GetSymbols)
+        endif
   endif
 
   ifneq (,$$($1_PROGRAM))
--- a/modules.xml	Thu Nov 12 18:27:55 2015 -0800
+++ b/modules.xml	Wed Jul 05 21:00:20 2017 +0200
@@ -229,8 +229,11 @@
       <to>java.logging</to>
       <to>java.management</to>
       <to>java.naming</to>
+      <to>java.security.jgss</to>
       <to>java.sql</to>
+      <to>java.xml</to>
       <to>jdk.management.resource</to>
+      <to>jdk.scripting.nashorn</to>
     </export>
     <export>
       <name>jdk.internal.org.objectweb.asm</name>
--- a/test/lib/sun/hotspot/code/CodeBlob.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/test/lib/sun/hotspot/code/CodeBlob.java	Wed Jul 05 21:00:20 2017 +0200
@@ -47,22 +47,24 @@
     return new CodeBlob(obj);
   }
   protected CodeBlob(Object[] obj) {
-    assert obj.length == 3;
+    assert obj.length == 4;
     name = (String) obj[0];
     size = (Integer) obj[1];
     code_blob_type = BlobType.values()[(Integer) obj[2]];
     assert code_blob_type.id == (Integer) obj[2];
+    address = (Long) obj[3];
   }
   public final String name;
   public final int size;
   public final BlobType code_blob_type;
-
+  public final long address;
   @Override
   public String toString() {
     return "CodeBlob{"
         + "name=" + name
         + ", size=" + size
         + ", code_blob_type=" + code_blob_type
+        + ", address=" + address
         + '}';
   }
 }
--- a/test/lib/sun/hotspot/code/NMethod.java	Thu Nov 12 18:27:55 2015 -0800
+++ b/test/lib/sun/hotspot/code/NMethod.java	Wed Jul 05 21:00:20 2017 +0200
@@ -39,12 +39,12 @@
     comp_level = (Integer) obj[1];
     insts = (byte[]) obj[2];
     compile_id = (Integer) obj[3];
-    address = (Long) obj[4];
+    entry_point = (Long) obj[4];
   }
   public final byte[] insts;
   public final int comp_level;
   public final int compile_id;
-  public final long address;
+  public final long entry_point;
 
   @Override
   public String toString() {
@@ -53,7 +53,7 @@
         + ", insts=" + insts
         + ", comp_level=" + comp_level
         + ", compile_id=" + compile_id
-        + ", address=" + address
+        + ", entry_point=" + entry_point
         + '}';
   }
 }