Merge
authorneliasso
Fri, 06 Nov 2015 11:34:03 +0100
changeset 33638 ef49ed90010b
parent 33626 3c94db05e903 (current diff)
parent 33637 f62a5a399b21 (diff)
child 33639 e672d407c0d9
Merge
hotspot/make/linux/makefiles/gcc.make
hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
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/src/share/vm/c1/c1_Canonicalizer.cpp
hotspot/src/share/vm/c1/c1_Compiler.cpp
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/classfile/javaClasses.cpp
hotspot/src/share/vm/classfile/javaClasses.hpp
hotspot/src/share/vm/classfile/symbolTable.cpp
hotspot/src/share/vm/classfile/symbolTable.hpp
hotspot/src/share/vm/classfile/vmSymbols.cpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/code/nmethod.cpp
hotspot/src/share/vm/code/nmethod.hpp
hotspot/src/share/vm/compiler/abstractCompiler.hpp
hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
hotspot/src/share/vm/jvmci/jvmciCompiler.cpp
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp
hotspot/src/share/vm/jvmci/jvmciEnv.cpp
hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp
hotspot/src/share/vm/jvmci/jvmciRuntime.cpp
hotspot/src/share/vm/memory/metaspaceShared.cpp
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/src/share/vm/oops/methodData.cpp
hotspot/src/share/vm/oops/methodData.hpp
hotspot/src/share/vm/opto/c2compiler.cpp
hotspot/src/share/vm/opto/lcm.cpp
hotspot/src/share/vm/opto/library_call.cpp
hotspot/src/share/vm/opto/macro.cpp
hotspot/src/share/vm/prims/jni.cpp
hotspot/src/share/vm/prims/jvmtiEnv.cpp
hotspot/src/share/vm/prims/jvmtiTagMap.cpp
hotspot/src/share/vm/runtime/arguments.cpp
hotspot/src/share/vm/runtime/deoptimization.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/src/share/vm/runtime/thread.cpp
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/compilerToVM/GetConstantPoolTest.java
hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.config
hotspot/test/compiler/jvmci/events/JvmciCompleteInitializationTest.java
--- a/hotspot/.hgignore	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/.hgignore	Fri Nov 06 11:34:03 2015 +0100
@@ -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/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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/gensrc/Gensrc-jdk.vm.ci.gmk	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/make/linux/makefiles/gcc.make	Fri Nov 06 11:34:03 2015 +0100
@@ -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)
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/globals_ppc.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/ppc.ad	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad	Fri Nov 06 11:34:03 2015 +0100
@@ -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/sparc/vm/assembler_sparc.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/nativeInst_sparc.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/sparc.ad	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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()) {
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/jvmciCodeInstaller_x86.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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,67 @@
   // 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 {
+    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 +7014,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 +7054,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 +7083,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 +7098,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 +7125,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 +7151,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 +7172,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 +7193,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 +7214,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 +7226,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 +7406,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 +7417,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 +7454,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 +7506,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 +7542,8 @@
   }
 }
 
+#endif
+
 void MacroAssembler::generate_fill(BasicType t, bool aligned,
                                    Register to, Register value, Register count,
                                    Register rtmp, XMMRegister xtmp) {
@@ -9085,6 +9548,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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/vmStructs_x86.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/InstalledCode.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Location.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Register.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterValue.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SourceStackTrace.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackLockValue.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/StackSlot.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/TargetDescription.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/ValueUtil.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/package-info.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/InspectedFrame.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/stack/StackIntrospection.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/JVMCIError.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledNmethod.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompressedNullConstant.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstant.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotInstalledCode.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJavaType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstant.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaspaceConstantImpl.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstant.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotOopMap.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaField.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSentinelConstant.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSignature.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotStackFrameReference.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedField.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotUnresolvedJavaType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMEventListener.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/MetaspaceWrapperObject.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/Stable.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/events/EmptyEventProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMManual.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ConstantReflectionProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/DefaultProfilingInfo.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ExceptionHandler.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JVMCIMetaAccessContext.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaField.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaKind.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethod.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaMethodProfile.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/JavaTypeProfile.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LIRKind.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTableImpl.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocationIdentity.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaAccessProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MethodHandleAccessProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PlatformKind.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/PrimitiveConstant.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaField.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SerializableConstant.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SpeculationLog.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options.processor/src/jdk/vm/ci/options/processor/OptionProcessor.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/DerivedOptionValue.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/NestedBooleanOptionValue.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/Option.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionValue.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsLoader.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCI.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIBackend.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/JVMCIRuntime.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service.processor/src/jdk/vm/ci/service/processor/ServiceProviderProcessor.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/.checkstyle_checks.xml	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/ServiceProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.service/src/jdk/vm/ci/service/Services.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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/solaris/vm/os_solaris.inline.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/share/vm/adlc/formssel.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/adlc/formssel.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/adlc/main.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/c1/c1_Canonicalizer.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -728,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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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_GraphBuilder.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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;
   }
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/ci/ciTypeArray.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/ci/ciTypeArray.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/ci/ciTypeArray.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/classfile/javaClasses.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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,16 +160,39 @@
   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;
@@ -179,26 +201,44 @@
   // 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("\"");
 }
@@ -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) {
@@ -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
 
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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);
--- a/hotspot/src/share/vm/classfile/stringTable.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/classfile/stringTable.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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);
 }
 
 
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -165,7 +165,7 @@
   // 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);
 
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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")                                    \
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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;
@@ -3388,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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/gc/g1/g1StringDedupTable.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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,
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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()) {
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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.
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -97,6 +97,8 @@
   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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/jvmciJavaClasses.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciJavaClasses.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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:                                                                                                                                                     \
--- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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.";
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/systemDictionary_jvmci.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/jvmci/vmSymbols_jvmci.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/filemap.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/memory/filemap.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/memory/filemap.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/metaspaceShared.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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].
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -2935,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();
--- a/hotspot/src/share/vm/oops/methodData.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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.
--- a/hotspot/src/share/vm/oops/methodData.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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,
--- a/hotspot/src/share/vm/oops/typeArrayOop.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/classes.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/classes.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/escape.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/escape.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/gcm.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/graphKit.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/idealKit.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/idealKit.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/intrinsicnode.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/intrinsicnode.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/lcm.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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;
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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;
+  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;
 }
 
@@ -4189,12 +4300,6 @@
   return true;
 }
 
-#ifdef _LP64
-#define XTOP ,top() /*additional argument*/
-#else  //_LP64
-#define XTOP        /*no additional argument*/
-#endif //_LP64
-
 //----------------------inline_unsafe_copyMemory-------------------------
 // public native void Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
 bool LibraryCallKit::inline_unsafe_copyMemory() {
@@ -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) {
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/loopnode.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/macro.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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);
--- a/hotspot/src/share/vm/opto/matcher.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/stringopts.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/stringopts.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/opto/stringopts.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/prims/jni.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/prims/jni.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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
@@ -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
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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;
   }
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/arguments.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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
 
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/globals.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -2880,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; "          \
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/thread.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/utilities/utf8.cpp	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/utilities/utf8.cpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/src/share/vm/utilities/utf8.hpp	Fri Nov 06 11:34:03 2015 +0100
@@ -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/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/intrinsics/unsafe/HeapByteBufferTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/SecurityRestrictionsTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/common/CompilerToVMHelper.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/common/JVMCIHelpers.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ /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	Fri Nov 06 11:34:03 2015 +0100
@@ -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	Fri Nov 06 11:34:03 2015 +0100
@@ -0,0 +1,1 @@
+compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory
--- a/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java	Thu Nov 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/CompileCodeTestCase.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetBytecodeTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -27,13 +27,13 @@
  * @bug 8136421
  * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64"
  * @library /testlibrary /../../test/lib /
- * @ignore 8139385
- * @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
@@ -41,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;
@@ -57,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);
@@ -83,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());
@@ -100,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);
@@ -118,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);
@@ -135,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,
@@ -145,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);
         }
@@ -181,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) {
@@ -191,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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetImplementorTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetSymbolTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/LookupTypeTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ReprofileTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveMethodTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ /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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/NestedBooleanOptionValueTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.options.test/src/jdk/vm/ci/options/test/TestOptionValue.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/FieldUniverse.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/MethodUniverse.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/NameAndSignature.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TypeUniverse.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Annotations/TestAnnotatedStringEncoding.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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/SharedArchiveFile/CdsDifferentCompactStrings.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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 05 19:31:57 2015 +0100
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Fri Nov 06 11:34:03 2015 +0100
@@ -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);
+    }
 }