changeset 39453:37e940028e4b

Merge
author amurillo
date Fri, 01 Jul 2016 16:50:34 -0700
parents 03e7b2c5ae34 eebe070746ad
children 94a6f2e7f4ee e42ae81241c5 7e74a94e5b75
files hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigVerifier.java hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMAddress.java hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMConstant.java hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMData.java hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMField.java hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMFlag.java hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspotvmconfig/src/jdk/vm/ci/hotspotvmconfig/HotSpotVMType.java hotspot/src/share/vm/runtime/atomic.cpp
diffstat 459 files changed, 7993 insertions(+), 6353 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/.mx.jvmci/mx_jvmci.py	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/.mx.jvmci/mx_jvmci.py	Fri Jul 01 16:50:34 2016 -0700
@@ -186,7 +186,8 @@
             # Might be building with JDK8 which has cacerts under jre/
             srcCerts = join(mx.get_jdk(tag='default').home, 'jre', 'lib', 'security', 'cacerts')
         dstCerts = join(jdkImageDir, 'lib', 'security', 'cacerts')
-        shutil.copyfile(srcCerts, dstCerts)
+        if srcCerts != dstCerts:
+            shutil.copyfile(srcCerts, dstCerts)
 
         _create_jdk_bundle(jdkBuildDir, _vm.debugLevel, jdkImageDir)
 
--- a/hotspot/.mx.jvmci/suite.py	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/.mx.jvmci/suite.py	Fri Jul 01 16:50:34 2016 -0700
@@ -149,7 +149,6 @@
       "subDir" : "src/jdk.vm.ci/share/classes",
       "sourceDirs" : ["src"],
       "dependencies" : [
-        "jdk.vm.ci.hotspotvmconfig",
         "jdk.vm.ci.common",
         "jdk.vm.ci.runtime",
         "jdk.vm.ci.services",
@@ -175,14 +174,6 @@
       "workingSets" : "API,JVMCI",
     },
 
-    "jdk.vm.ci.hotspotvmconfig" : {
-      "subDir" : "src/jdk.vm.ci/share/classes",
-      "sourceDirs" : ["src"],
-      "checkstyle" : "jdk.vm.ci.services",
-      "javaCompliance" : "9",
-      "workingSets" : "JVMCI,HotSpot",
-    },
-
     "jdk.vm.ci.hotspot.aarch64" : {
       "subDir" : "src/jdk.vm.ci/share/classes",
       "sourceDirs" : ["src"],
@@ -248,13 +239,6 @@
       ],
     },
 
-    "JVMCI_HOTSPOTVMCONFIG" : {
-      "subDir" : "src/jdk.vm.ci/share/classes",
-      "dependencies" : [
-        "jdk.vm.ci.hotspotvmconfig",
-      ],
-    },
-
     "JVMCI_HOTSPOT" : {
       "subDir" : "src/jdk.vm.ci/share/classes",
       "dependencies" : [
@@ -263,7 +247,6 @@
         "jdk.vm.ci.hotspot.sparc",
       ],
       "distDependencies" : [
-        "JVMCI_HOTSPOTVMCONFIG",
         "JVMCI_SERVICES",
         "JVMCI_API",
       ],
--- a/hotspot/make/lib/CompileGtest.gmk	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/make/lib/CompileGtest.gmk	Fri Jul 01 16:50:34 2016 -0700
@@ -23,7 +23,10 @@
 # questions.
 #
 
-GTEST_TEST_SRC := $(HOTSPOT_TOPDIR)/test/native
+$(eval $(call IncludeCustomExtension, hotspot, lib/CompileGtest.gmk))
+
+GTEST_TEST_SRC += $(HOTSPOT_TOPDIR)/test/native
+GTEST_LAUNCHER_SRC := $(HOTSPOT_TOPDIR)/test/native/gtestLauncher.cpp
 GTEST_FRAMEWORK_SRC := $(SRC_ROOT)/test/fmw/gtest
 
 # On Windows, there are no internal debug symbols so must set copying to true
@@ -65,7 +68,7 @@
         $(BUILD_LIBJVM_ALL_OBJS)), \
     CFLAGS := $(JVM_CFLAGS) -I$(GTEST_FRAMEWORK_SRC) \
         -I$(GTEST_FRAMEWORK_SRC)/include \
-        -I$(GTEST_TEST_SRC), \
+        $(addprefix -I,$(GTEST_TEST_SRC)), \
     CFLAGS_windows := /EHsc, \
     CFLAGS_solaris := -DGTEST_HAS_EXCEPTIONS=0 -library=stlport4, \
     CFLAGS_macosx := -DGTEST_OS_MAC=1, \
@@ -73,7 +76,7 @@
     CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
     DISABLED_WARNINGS_gcc := undef, \
     DISABLED_WARNINGS_clang := undef switch format-nonliteral \
-        tautological-undefined-compare, \
+        tautological-undefined-compare $(BUILD_LIBJVM_DISABLED_WARNINGS_clang), \
     DISABLED_WARNINGS_solstudio := identexpected, \
     LDFLAGS := $(JVM_LDFLAGS), \
     LDFLAGS_solaris := -library=stlport4 $(call SET_SHARED_LIBRARY_ORIGIN), \
@@ -83,6 +86,8 @@
     USE_MAPFILE_FOR_SYMBOLS := true, \
     COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
     ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
+    PRECOMPILED_HEADER := $(JVM_PRECOMPILED_HEADER), \
+    PRECOMPILED_HEADER_EXCLUDE := gtest-all.cc gtestMain.cpp, \
 ))
 
 TARGETS += $(BUILD_GTEST_LIBJVM)
@@ -93,7 +98,7 @@
     TOOLCHAIN := $(JVM_TOOLCHAIN), \
     PROGRAM := gtestLauncher, \
     OUTPUT_DIR := $(JVM_OUTPUTDIR)/gtest, \
-    EXTRA_FILES := $(GTEST_TEST_SRC)/gtestLauncher.cpp, \
+    EXTRA_FILES := $(GTEST_LAUNCHER_SRC), \
     OBJECT_DIR := $(JVM_OUTPUTDIR)/gtest/launcher-objs, \
     CFLAGS := $(JVM_CFLAGS) -I$(GTEST_FRAMEWORK_SRC) \
         -I$(GTEST_FRAMEWORK_SRC)/include, \
--- a/hotspot/make/lib/JvmOverrideFiles.gmk	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/make/lib/JvmOverrideFiles.gmk	Fri Jul 01 16:50:34 2016 -0700
@@ -35,6 +35,7 @@
 
 ifeq ($(OPENJDK_TARGET_OS), linux)
   BUILD_LIBJVM_ostream.cpp_CXXFLAGS := -D_FILE_OFFSET_BITS=64
+  BUILD_LIBJVM_logFileOutput.cpp_CXXFLAGS := -D_FILE_OFFSET_BITS=64
 
   ifeq ($(OPENJDK_TARGET_CPU_ARCH), x86)
     BUILD_LIBJVM_sharedRuntimeTrig.cpp_CXXFLAGS := -DNO_PCH $(CXX_O_FLAG_NONE)
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad	Fri Jul 01 16:50:34 2016 -0700
@@ -6629,6 +6629,82 @@
   %}
 %}
 
+// used for certain integral comparisons which can be
+// converted to cbxx or tbxx instructions
+
+operand cmpOpEqNe()
+%{
+  match(Bool);
+  match(CmpOp);
+  op_cost(0);
+  predicate(n->as_Bool()->_test._test == BoolTest::ne
+            || n->as_Bool()->_test._test == BoolTest::eq);
+
+  format %{ "" %}
+  interface(COND_INTER) %{
+    equal(0x0, "eq");
+    not_equal(0x1, "ne");
+    less(0xb, "lt");
+    greater_equal(0xa, "ge");
+    less_equal(0xd, "le");
+    greater(0xc, "gt");
+    overflow(0x6, "vs");
+    no_overflow(0x7, "vc");
+  %}
+%}
+
+// used for certain integral comparisons which can be
+// converted to cbxx or tbxx instructions
+
+operand cmpOpLtGe()
+%{
+  match(Bool);
+  match(CmpOp);
+  op_cost(0);
+
+  predicate(n->as_Bool()->_test._test == BoolTest::lt
+            || n->as_Bool()->_test._test == BoolTest::ge);
+
+  format %{ "" %}
+  interface(COND_INTER) %{
+    equal(0x0, "eq");
+    not_equal(0x1, "ne");
+    less(0xb, "lt");
+    greater_equal(0xa, "ge");
+    less_equal(0xd, "le");
+    greater(0xc, "gt");
+    overflow(0x6, "vs");
+    no_overflow(0x7, "vc");
+  %}
+%}
+
+// used for certain unsigned integral comparisons which can be
+// converted to cbxx or tbxx instructions
+
+operand cmpOpUEqNeLtGe()
+%{
+  match(Bool);
+  match(CmpOp);
+  op_cost(0);
+
+  predicate(n->as_Bool()->_test._test == BoolTest::eq
+            || n->as_Bool()->_test._test == BoolTest::ne
+            || n->as_Bool()->_test._test == BoolTest::lt
+            || n->as_Bool()->_test._test == BoolTest::ge);
+
+  format %{ "" %}
+  interface(COND_INTER) %{
+    equal(0x0, "eq");
+    not_equal(0x1, "ne");
+    less(0xb, "lt");
+    greater_equal(0xa, "ge");
+    less_equal(0xd, "le");
+    greater(0xc, "gt");
+    overflow(0x6, "vs");
+    no_overflow(0x7, "vc");
+  %}
+%}
+
 // Special operand allowing long args to int ops to be truncated for free
 
 operand iRegL2I(iRegL reg) %{
@@ -14286,10 +14362,8 @@
 // shorter than (cmp; branch), have the additional benefit of not
 // killing the flags.
 
-instruct cmpI_imm0_branch(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl, rFlagsReg cr) %{
+instruct cmpI_imm0_branch(cmpOpEqNe cmp, iRegIorL2I op1, immI0 op2, label labl, rFlagsReg cr) %{
   match(If cmp (CmpI op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14305,10 +14379,8 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct cmpL_imm0_branch(cmpOp cmp, iRegL op1, immL0 op2, label labl, rFlagsReg cr) %{
+instruct cmpL_imm0_branch(cmpOpEqNe cmp, iRegL op1, immL0 op2, label labl, rFlagsReg cr) %{
   match(If cmp (CmpL op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14324,10 +14396,8 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct cmpP_imm0_branch(cmpOp cmp, iRegP op1, immP0 op2, label labl, rFlagsReg cr) %{
+instruct cmpP_imm0_branch(cmpOpEqNe cmp, iRegP op1, immP0 op2, label labl, rFlagsReg cr) %{
   match(If cmp (CmpP op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14343,10 +14413,8 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct cmpN_imm0_branch(cmpOp cmp, iRegN op1, immN0 op2, label labl, rFlagsReg cr) %{
+instruct cmpN_imm0_branch(cmpOpEqNe cmp, iRegN op1, immN0 op2, label labl, rFlagsReg cr) %{
   match(If cmp (CmpN op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
-	    || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14362,10 +14430,8 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl, rFlagsReg cr) %{
+instruct cmpP_narrowOop_imm0_branch(cmpOpEqNe cmp, iRegN oop, immP0 zero, label labl, rFlagsReg cr) %{
   match(If cmp (CmpP (DecodeN oop) zero));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14381,12 +14447,8 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct cmpUI_imm0_branch(cmpOpU cmp, iRegIorL2I op1, immI0 op2, label labl, rFlagsRegU cr) %{
+instruct cmpUI_imm0_branch(cmpOpUEqNeLtGe cmp, iRegIorL2I op1, immI0 op2, label labl, rFlagsRegU cr) %{
   match(If cmp (CmpU op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq
-            || n->in(1)->as_Bool()->_test._test == BoolTest::gt
-            ||  n->in(1)->as_Bool()->_test._test == BoolTest::le);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14402,12 +14464,8 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct cmpUL_imm0_branch(cmpOpU cmp, iRegL op1, immL0 op2, label labl, rFlagsRegU cr) %{
+instruct cmpUL_imm0_branch(cmpOpUEqNeLtGe cmp, iRegL op1, immL0 op2, label labl, rFlagsRegU cr) %{
   match(If cmp (CmpU op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq
-            || n->in(1)->as_Bool()->_test._test == BoolTest::gt
-            || n->in(1)->as_Bool()->_test._test == BoolTest::le);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14426,10 +14484,8 @@
 // Test bit and Branch
 
 // Patterns for short (< 32KiB) variants
-instruct cmpL_branch_sign(cmpOp cmp, iRegL op1, immL0 op2, label labl) %{
+instruct cmpL_branch_sign(cmpOpLtGe cmp, iRegL op1, immL0 op2, label labl) %{
   match(If cmp (CmpL op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
-            || n->in(1)->as_Bool()->_test._test == BoolTest::ge);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14444,10 +14500,8 @@
   ins_short_branch(1);
 %}
 
-instruct cmpI_branch_sign(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl) %{
+instruct cmpI_branch_sign(cmpOpLtGe cmp, iRegIorL2I op1, immI0 op2, label labl) %{
   match(If cmp (CmpI op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
-            || n->in(1)->as_Bool()->_test._test == BoolTest::ge);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14462,11 +14516,9 @@
   ins_short_branch(1);
 %}
 
-instruct cmpL_branch_bit(cmpOp cmp, iRegL op1, immL op2, immL0 op3, label labl) %{
+instruct cmpL_branch_bit(cmpOpEqNe cmp, iRegL op1, immL op2, immL0 op3, label labl) %{
   match(If cmp (CmpL (AndL op1 op2) op3));
-  predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq)
-            && is_power_of_2(n->in(2)->in(1)->in(2)->get_long()));
+  predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_long()));
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14481,11 +14533,9 @@
   ins_short_branch(1);
 %}
 
-instruct cmpI_branch_bit(cmpOp cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl) %{
+instruct cmpI_branch_bit(cmpOpEqNe cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl) %{
   match(If cmp (CmpI (AndI op1 op2) op3));
-  predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq)
-            && is_power_of_2(n->in(2)->in(1)->in(2)->get_int()));
+  predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_int()));
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14501,10 +14551,8 @@
 %}
 
 // And far variants
-instruct far_cmpL_branch_sign(cmpOp cmp, iRegL op1, immL0 op2, label labl) %{
+instruct far_cmpL_branch_sign(cmpOpLtGe cmp, iRegL op1, immL0 op2, label labl) %{
   match(If cmp (CmpL op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
-            || n->in(1)->as_Bool()->_test._test == BoolTest::ge);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14518,10 +14566,8 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct far_cmpI_branch_sign(cmpOp cmp, iRegIorL2I op1, immI0 op2, label labl) %{
+instruct far_cmpI_branch_sign(cmpOpLtGe cmp, iRegIorL2I op1, immI0 op2, label labl) %{
   match(If cmp (CmpI op1 op2));
-  predicate(n->in(1)->as_Bool()->_test._test == BoolTest::lt
-            || n->in(1)->as_Bool()->_test._test == BoolTest::ge);
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14535,11 +14581,9 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct far_cmpL_branch_bit(cmpOp cmp, iRegL op1, immL op2, immL0 op3, label labl) %{
+instruct far_cmpL_branch_bit(cmpOpEqNe cmp, iRegL op1, immL op2, immL0 op3, label labl) %{
   match(If cmp (CmpL (AndL op1 op2) op3));
-  predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq)
-            && is_power_of_2(n->in(2)->in(1)->in(2)->get_long()));
+  predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_long()));
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
@@ -14553,11 +14597,9 @@
   ins_pipe(pipe_cmp_branch);
 %}
 
-instruct far_cmpI_branch_bit(cmpOp cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl) %{
+instruct far_cmpI_branch_bit(cmpOpEqNe cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl) %{
   match(If cmp (CmpI (AndI op1 op2) op3));
-  predicate((n->in(1)->as_Bool()->_test._test == BoolTest::ne
-            || n->in(1)->as_Bool()->_test._test == BoolTest::eq)
-            && is_power_of_2(n->in(2)->in(1)->in(2)->get_int()));
+  predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_int()));
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -630,7 +630,11 @@
   __ b(do_continue);
 }
 
-// See if we've got enough room on the stack for locals plus overhead.
+// See if we've got enough room on the stack for locals plus overhead
+// below JavaThread::stack_overflow_limit(). If not, throw a StackOverflowError
+// without going through the signal handler, i.e., reserved and yellow zones
+// will not be made usable. The shadow zone must suffice to handle the
+// overflow.
 // The expression stack grows down incrementally, so the normal guard
 // page mechanism will work for that.
 //
@@ -674,40 +678,25 @@
   // compute rsp as if this were going to be the last frame on
   // the stack before the red zone
 
-  const Address stack_base(rthread, Thread::stack_base_offset());
-  const Address stack_size(rthread, Thread::stack_size_offset());
-
   // locals + overhead, in bytes
   __ mov(r0, overhead_size);
   __ add(r0, r0, r3, Assembler::LSL, Interpreter::logStackElementSize);  // 2 slots per parameter.
 
-  __ ldr(rscratch1, stack_base);
-  __ ldr(rscratch2, stack_size);
+  const Address stack_limit(rthread, JavaThread::stack_overflow_limit_offset());
+  __ ldr(rscratch1, stack_limit);
 
 #ifdef ASSERT
-  Label stack_base_okay, stack_size_okay;
-  // verify that thread stack base is non-zero
-  __ cbnz(rscratch1, stack_base_okay);
-  __ stop("stack base is zero");
-  __ bind(stack_base_okay);
-  // verify that thread stack size is non-zero
-  __ cbnz(rscratch2, stack_size_okay);
-  __ stop("stack size is zero");
-  __ bind(stack_size_okay);
+  Label limit_okay;
+  // Verify that thread stack limit is non-zero.
+  __ cbnz(rscratch1, limit_okay);
+  __ stop("stack overflow limit is zero");
+  __ bind(limit_okay);
 #endif
 
-  // Add stack base to locals and subtract stack size
-  __ sub(rscratch1, rscratch1, rscratch2); // Stack limit
+  // Add stack limit to locals.
   __ add(r0, r0, rscratch1);
 
-  // Use the bigger size for banging.
-  const int max_bang_size = MAX2(JavaThread::stack_shadow_zone_size(),
-                                 JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size());
-
-  // add in the red and yellow zone sizes
-  __ add(r0, r0, max_bang_size * 2);
-
-  // check against the current stack bottom
+  // Check against the current stack bottom.
   __ cmp(sp, r0);
   __ br(Assembler::HI, after_frame_check);
 
@@ -1088,9 +1077,9 @@
   __ ldr(r2, constMethod);
   __ load_unsigned_short(r2, size_of_parameters);
 
-  // native calls don't need the stack size check since they have no
+  // Native calls don't need the stack size check since they have no
   // expression stack and the arguments are already on the stack and
-  // we only add a handful of words to the stack
+  // we only add a handful of words to the stack.
 
   // rmethod: Method*
   // r2: size of parameters
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp	Fri Jul 01 16:50:34 2016 -0700
@@ -706,9 +706,13 @@
     TW_OPCODE      = (31u << OPCODE_SHIFT |    4u << 1),
 
     // Atomics.
+    LBARX_OPCODE   = (31u << OPCODE_SHIFT |   52u << 1),
+    LHARX_OPCODE   = (31u << OPCODE_SHIFT |  116u << 1),
     LWARX_OPCODE   = (31u << OPCODE_SHIFT |   20u << 1),
     LDARX_OPCODE   = (31u << OPCODE_SHIFT |   84u << 1),
     LQARX_OPCODE   = (31u << OPCODE_SHIFT |  276u << 1),
+    STBCX_OPCODE   = (31u << OPCODE_SHIFT |  694u << 1),
+    STHCX_OPCODE   = (31u << OPCODE_SHIFT |  726u << 1),
     STWCX_OPCODE   = (31u << OPCODE_SHIFT |  150u << 1),
     STDCX_OPCODE   = (31u << OPCODE_SHIFT |  214u << 1),
     STQCX_OPCODE   = (31u << OPCODE_SHIFT |  182u << 1)
@@ -1796,13 +1800,19 @@
   inline void waitrsv(); // >=Power7
 
   // atomics
+  inline void lbarx_unchecked(Register d, Register a, Register b, int eh1 = 0); // >=Power 8
+  inline void lharx_unchecked(Register d, Register a, Register b, int eh1 = 0); // >=Power 8
   inline void lwarx_unchecked(Register d, Register a, Register b, int eh1 = 0);
   inline void ldarx_unchecked(Register d, Register a, Register b, int eh1 = 0);
-  inline void lqarx_unchecked(Register d, Register a, Register b, int eh1 = 0);
+  inline void lqarx_unchecked(Register d, Register a, Register b, int eh1 = 0); // >=Power 8
   inline bool lxarx_hint_exclusive_access();
+  inline void lbarx(  Register d, Register a, Register b, bool hint_exclusive_access = false);
+  inline void lharx(  Register d, Register a, Register b, bool hint_exclusive_access = false);
   inline void lwarx(  Register d, Register a, Register b, bool hint_exclusive_access = false);
   inline void ldarx(  Register d, Register a, Register b, bool hint_exclusive_access = false);
   inline void lqarx(  Register d, Register a, Register b, bool hint_exclusive_access = false);
+  inline void stbcx_( Register s, Register a, Register b);
+  inline void sthcx_( Register s, Register a, Register b);
   inline void stwcx_( Register s, Register a, Register b);
   inline void stdcx_( Register s, Register a, Register b);
   inline void stqcx_( Register s, Register a, Register b);
@@ -2169,12 +2179,18 @@
   inline void dcbtstct(Register s2, int ct);
 
   // Atomics: use ra0mem to disallow R0 as base.
+  inline void lbarx_unchecked(Register d, Register b, int eh1);
+  inline void lharx_unchecked(Register d, Register b, int eh1);
   inline void lwarx_unchecked(Register d, Register b, int eh1);
   inline void ldarx_unchecked(Register d, Register b, int eh1);
   inline void lqarx_unchecked(Register d, Register b, int eh1);
+  inline void lbarx( Register d, Register b, bool hint_exclusive_access);
+  inline void lharx( Register d, Register b, bool hint_exclusive_access);
   inline void lwarx( Register d, Register b, bool hint_exclusive_access);
   inline void ldarx( Register d, Register b, bool hint_exclusive_access);
   inline void lqarx( Register d, Register b, bool hint_exclusive_access);
+  inline void stbcx_(Register s, Register b);
+  inline void sthcx_(Register s, Register b);
   inline void stwcx_(Register s, Register b);
   inline void stdcx_(Register s, Register b);
   inline void stqcx_(Register s, Register b);
--- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Fri Jul 01 16:50:34 2016 -0700
@@ -594,13 +594,19 @@
 
 // atomics
 // Use ra0mem to disallow R0 as base.
+inline void Assembler::lbarx_unchecked(Register d, Register a, Register b, int eh1)           { emit_int32( LBARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); }
+inline void Assembler::lharx_unchecked(Register d, Register a, Register b, int eh1)           { emit_int32( LHARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); }
 inline void Assembler::lwarx_unchecked(Register d, Register a, Register b, int eh1)           { emit_int32( LWARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); }
 inline void Assembler::ldarx_unchecked(Register d, Register a, Register b, int eh1)           { emit_int32( LDARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); }
 inline void Assembler::lqarx_unchecked(Register d, Register a, Register b, int eh1)           { emit_int32( LQARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); }
 inline bool Assembler::lxarx_hint_exclusive_access()                                          { return VM_Version::has_lxarxeh(); }
+inline void Assembler::lbarx( Register d, Register a, Register b, bool hint_exclusive_access) { lbarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
+inline void Assembler::lharx( Register d, Register a, Register b, bool hint_exclusive_access) { lharx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
 inline void Assembler::lwarx( Register d, Register a, Register b, bool hint_exclusive_access) { lwarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
 inline void Assembler::ldarx( Register d, Register a, Register b, bool hint_exclusive_access) { ldarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
 inline void Assembler::lqarx( Register d, Register a, Register b, bool hint_exclusive_access) { lqarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
+inline void Assembler::stbcx_(Register s, Register a, Register b)                             { emit_int32( STBCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
+inline void Assembler::sthcx_(Register s, Register a, Register b)                             { emit_int32( STHCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
 inline void Assembler::stwcx_(Register s, Register a, Register b)                             { emit_int32( STWCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
 inline void Assembler::stdcx_(Register s, Register a, Register b)                             { emit_int32( STDCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
 inline void Assembler::stqcx_(Register s, Register a, Register b)                             { emit_int32( STQCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
@@ -933,12 +939,18 @@
 inline void Assembler::dcbtstct(Register s2, int ct)  { emit_int32( DCBTST_OPCODE | rb(s2) | thct(ct)); }
 
 // ra0 version
+inline void Assembler::lbarx_unchecked(Register d, Register b, int eh1)          { emit_int32( LBARX_OPCODE | rt(d) | rb(b) | eh(eh1)); }
+inline void Assembler::lharx_unchecked(Register d, Register b, int eh1)          { emit_int32( LHARX_OPCODE | rt(d) | rb(b) | eh(eh1)); }
 inline void Assembler::lwarx_unchecked(Register d, Register b, int eh1)          { emit_int32( LWARX_OPCODE | rt(d) | rb(b) | eh(eh1)); }
 inline void Assembler::ldarx_unchecked(Register d, Register b, int eh1)          { emit_int32( LDARX_OPCODE | rt(d) | rb(b) | eh(eh1)); }
 inline void Assembler::lqarx_unchecked(Register d, Register b, int eh1)          { emit_int32( LQARX_OPCODE | rt(d) | rb(b) | eh(eh1)); }
+inline void Assembler::lbarx( Register d, Register b, bool hint_exclusive_access){ lbarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
+inline void Assembler::lharx( Register d, Register b, bool hint_exclusive_access){ lharx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
 inline void Assembler::lwarx( Register d, Register b, bool hint_exclusive_access){ lwarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
 inline void Assembler::ldarx( Register d, Register b, bool hint_exclusive_access){ ldarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
 inline void Assembler::lqarx( Register d, Register b, bool hint_exclusive_access){ lqarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
+inline void Assembler::stbcx_(Register s, Register b)                            { emit_int32( STBCX_OPCODE | rs(s) | rb(b) | rc(1)); }
+inline void Assembler::sthcx_(Register s, Register b)                            { emit_int32( STHCX_OPCODE | rs(s) | rb(b) | rc(1)); }
 inline void Assembler::stwcx_(Register s, Register b)                            { emit_int32( STWCX_OPCODE | rs(s) | rb(b) | rc(1)); }
 inline void Assembler::stdcx_(Register s, Register b)                            { emit_int32( STDCX_OPCODE | rs(s) | rb(b) | rc(1)); }
 inline void Assembler::stqcx_(Register s, Register b)                            { emit_int32( STQCX_OPCODE | rs(s) | rb(b) | rc(1)); }
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp	Fri Jul 01 16:50:34 2016 -0700
@@ -40,9 +40,9 @@
 define_pd_global(bool, TrapBasedNullChecks,   true);
 define_pd_global(bool, UncommonNullCast,      true);  // Uncommon-trap NULLs passed to check cast.
 
-#define DEFAULT_STACK_YELLOW_PAGES (6)
+#define DEFAULT_STACK_YELLOW_PAGES (2)
 #define DEFAULT_STACK_RED_PAGES (1)
-#define DEFAULT_STACK_SHADOW_PAGES (6 DEBUG_ONLY(+2))
+#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+2))
 #define DEFAULT_STACK_RESERVED_PAGES (1)
 
 #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -478,33 +478,6 @@
   profile_typecheck_failed(Rtmp1, Rtmp2);
 }
 
-void InterpreterMacroAssembler::generate_stack_overflow_check_with_compare_and_throw(Register Rmem_frame_size, Register Rscratch1) {
-  Label done;
-  BLOCK_COMMENT("stack_overflow_check_with_compare_and_throw {");
-  sub(Rmem_frame_size, R1_SP, Rmem_frame_size);
-  ld(Rscratch1, thread_(stack_overflow_limit));
-  cmpld(CCR0/*is_stack_overflow*/, Rmem_frame_size, Rscratch1);
-  bgt(CCR0/*is_stack_overflow*/, done);
-
-  // Load target address of the runtime stub.
-  assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "generated in wrong order");
-  load_const_optimized(Rscratch1, (StubRoutines::throw_StackOverflowError_entry()), R0);
-  mtctr(Rscratch1);
-  // Restore caller_sp.
-#ifdef ASSERT
-  ld(Rscratch1, 0, R1_SP);
-  ld(R0, 0, R21_sender_SP);
-  cmpd(CCR0, R0, Rscratch1);
-  asm_assert_eq("backlink", 0x547);
-#endif // ASSERT
-  mr(R1_SP, R21_sender_SP);
-  bctr();
-
-  align(32, 12);
-  bind(done);
-  BLOCK_COMMENT("} stack_overflow_check_with_compare_and_throw");
-}
-
 // Separate these two to allow for delay slot in middle.
 // These are used to do a test and full jump to exception-throwing code.
 
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp	Fri Jul 01 16:50:34 2016 -0700
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,6 @@
   // Load object from cpool->resolved_references(index).
   void load_resolved_reference_at_index(Register result, Register index, Label *is_null = NULL);
 
-  void generate_stack_overflow_check_with_compare_and_throw(Register Rmem_frame_size, Register Rscratch1);
   void load_receiver(Register Rparam_count, Register Rrecv_dst);
 
   // helpers for expression stack
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -1422,42 +1422,168 @@
   bind(no_reserved_zone_enabling);
 }
 
-// CmpxchgX sets condition register to cmpX(current, compare).
-void MacroAssembler::cmpxchgw(ConditionRegister flag, Register dest_current_value,
-                              Register compare_value, Register exchange_value,
-                              Register addr_base, int semantics, bool cmpxchgx_hint,
-                              Register int_flag_success, bool contention_hint, bool weak) {
+void MacroAssembler::getandsetd(Register dest_current_value, Register exchange_value, Register addr_base,
+                                bool cmpxchgx_hint) {
   Label retry;
-  Label failed;
-  Label done;
-
-  // Save one branch if result is returned via register and
-  // result register is different from the other ones.
-  bool use_result_reg    = (int_flag_success != noreg);
-  bool preset_result_reg = (int_flag_success != dest_current_value && int_flag_success != compare_value &&
-                            int_flag_success != exchange_value && int_flag_success != addr_base);
-  assert(!weak || flag == CCR0, "weak only supported with CCR0");
-
-  if (use_result_reg && preset_result_reg) {
-    li(int_flag_success, 0); // preset (assume cas failed)
+  bind(retry);
+  ldarx(dest_current_value, addr_base, cmpxchgx_hint);
+  stdcx_(exchange_value, addr_base);
+  if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
+    bne_predict_not_taken(CCR0, retry); // StXcx_ sets CCR0.
+  } else {
+    bne(                  CCR0, retry); // StXcx_ sets CCR0.
   }
-
-  // Add simple guard in order to reduce risk of starving under high contention (recommended by IBM).
-  if (contention_hint) { // Don't try to reserve if cmp fails.
-    lwz(dest_current_value, 0, addr_base);
-    cmpw(flag, dest_current_value, compare_value);
-    bne(flag, failed);
+}
+
+void MacroAssembler::getandaddd(Register dest_current_value, Register inc_value, Register addr_base,
+                                Register tmp, bool cmpxchgx_hint) {
+  Label retry;
+  bind(retry);
+  ldarx(dest_current_value, addr_base, cmpxchgx_hint);
+  add(tmp, dest_current_value, inc_value);
+  stdcx_(tmp, addr_base);
+  if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
+    bne_predict_not_taken(CCR0, retry); // StXcx_ sets CCR0.
+  } else {
+    bne(                  CCR0, retry); // StXcx_ sets CCR0.
   }
-
-  // release/fence semantics
-  if (semantics & MemBarRel) {
-    release();
+}
+
+// Word/sub-word atomic helper functions
+
+// Temps and addr_base are killed if size < 4 and processor does not support respective instructions.
+// Only signed types are supported with size < 4.
+// Atomic add always kills tmp1.
+void MacroAssembler::atomic_get_and_modify_generic(Register dest_current_value, Register exchange_value,
+                                                   Register addr_base, Register tmp1, Register tmp2, Register tmp3,
+                                                   bool cmpxchgx_hint, bool is_add, int size) {
+  // Sub-word instructions are available since Power 8.
+  // For older processors, instruction_type != size holds, and we
+  // emulate the sub-word instructions by constructing a 4-byte value
+  // that leaves the other bytes unchanged.
+  const int instruction_type = VM_Version::has_lqarx() ? size : 4;
+
+  Label retry;
+  Register shift_amount = noreg,
+           val32 = dest_current_value,
+           modval = is_add ? tmp1 : exchange_value;
+
+  if (instruction_type != size) {
+    assert_different_registers(tmp1, tmp2, tmp3, dest_current_value, exchange_value, addr_base);
+    modval = tmp1;
+    shift_amount = tmp2;
+    val32 = tmp3;
+    // Need some preperation: Compute shift amount, align address. Note: shorts must be 2 byte aligned.
+#ifdef VM_LITTLE_ENDIAN
+    rldic(shift_amount, addr_base, 3, 64-5); // (dest & 3) * 8;
+    clrrdi(addr_base, addr_base, 2);
+#else
+    xori(shift_amount, addr_base, (size == 1) ? 3 : 2);
+    clrrdi(addr_base, addr_base, 2);
+    rldic(shift_amount, shift_amount, 3, 64-5); // byte: ((3-dest) & 3) * 8; short: ((1-dest/2) & 1) * 16;
+#endif
   }
 
   // atomic emulation loop
   bind(retry);
 
-  lwarx(dest_current_value, addr_base, cmpxchgx_hint);
+  switch (instruction_type) {
+    case 4: lwarx(val32, addr_base, cmpxchgx_hint); break;
+    case 2: lharx(val32, addr_base, cmpxchgx_hint); break;
+    case 1: lbarx(val32, addr_base, cmpxchgx_hint); break;
+    default: ShouldNotReachHere();
+  }
+
+  if (instruction_type != size) {
+    srw(dest_current_value, val32, shift_amount);
+  }
+
+  if (is_add) { add(modval, dest_current_value, exchange_value); }
+
+  if (instruction_type != size) {
+    // Transform exchange value such that the replacement can be done by one xor instruction.
+    xorr(modval, dest_current_value, is_add ? modval : exchange_value);
+    clrldi(modval, modval, (size == 1) ? 56 : 48);
+    slw(modval, modval, shift_amount);
+    xorr(modval, val32, modval);
+  }
+
+  switch (instruction_type) {
+    case 4: stwcx_(modval, addr_base); break;
+    case 2: sthcx_(modval, addr_base); break;
+    case 1: stbcx_(modval, addr_base); break;
+    default: ShouldNotReachHere();
+  }
+
+  if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
+    bne_predict_not_taken(CCR0, retry); // StXcx_ sets CCR0.
+  } else {
+    bne(                  CCR0, retry); // StXcx_ sets CCR0.
+  }
+
+  // l?arx zero-extends, but Java wants byte/short values sign-extended.
+  if (size == 1) {
+    extsb(dest_current_value, dest_current_value);
+  } else if (size == 2) {
+    extsh(dest_current_value, dest_current_value);
+  };
+}
+
+// Temps, addr_base and exchange_value are killed if size < 4 and processor does not support respective instructions.
+// Only signed types are supported with size < 4.
+void MacroAssembler::cmpxchg_loop_body(ConditionRegister flag, Register dest_current_value,
+                                       Register compare_value, Register exchange_value,
+                                       Register addr_base, Register tmp1, Register tmp2,
+                                       Label &retry, Label &failed, bool cmpxchgx_hint, int size) {
+  // Sub-word instructions are available since Power 8.
+  // For older processors, instruction_type != size holds, and we
+  // emulate the sub-word instructions by constructing a 4-byte value
+  // that leaves the other bytes unchanged.
+  const int instruction_type = VM_Version::has_lqarx() ? size : 4;
+
+  Register shift_amount = noreg,
+           val32 = dest_current_value,
+           modval = exchange_value;
+
+  if (instruction_type != size) {
+    assert_different_registers(tmp1, tmp2, dest_current_value, compare_value, exchange_value, addr_base);
+    shift_amount = tmp1;
+    val32 = tmp2;
+    modval = tmp2;
+    // Need some preperation: Compute shift amount, align address. Note: shorts must be 2 byte aligned.
+#ifdef VM_LITTLE_ENDIAN
+    rldic(shift_amount, addr_base, 3, 64-5); // (dest & 3) * 8;
+    clrrdi(addr_base, addr_base, 2);
+#else
+    xori(shift_amount, addr_base, (size == 1) ? 3 : 2);
+    clrrdi(addr_base, addr_base, 2);
+    rldic(shift_amount, shift_amount, 3, 64-5); // byte: ((3-dest) & 3) * 8; short: ((1-dest/2) & 1) * 16;
+#endif
+    // Transform exchange value such that the replacement can be done by one xor instruction.
+    xorr(exchange_value, compare_value, exchange_value);
+    clrldi(exchange_value, exchange_value, (size == 1) ? 56 : 48);
+    slw(exchange_value, exchange_value, shift_amount);
+  }
+
+  // atomic emulation loop
+  bind(retry);
+
+  switch (instruction_type) {
+    case 4: lwarx(val32, addr_base, cmpxchgx_hint); break;
+    case 2: lharx(val32, addr_base, cmpxchgx_hint); break;
+    case 1: lbarx(val32, addr_base, cmpxchgx_hint); break;
+    default: ShouldNotReachHere();
+  }
+
+  if (instruction_type != size) {
+    srw(dest_current_value, val32, shift_amount);
+  }
+  if (size == 1) {
+    extsb(dest_current_value, dest_current_value);
+  } else if (size == 2) {
+    extsh(dest_current_value, dest_current_value);
+  };
+
   cmpw(flag, dest_current_value, compare_value);
   if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
     bne_predict_not_taken(flag, failed);
@@ -1467,7 +1593,60 @@
   // branch to done  => (flag == ne), (dest_current_value != compare_value)
   // fall through    => (flag == eq), (dest_current_value == compare_value)
 
-  stwcx_(exchange_value, addr_base);
+  if (instruction_type != size) {
+    xorr(modval, val32, exchange_value);
+  }
+
+  switch (instruction_type) {
+    case 4: stwcx_(modval, addr_base); break;
+    case 2: sthcx_(modval, addr_base); break;
+    case 1: stbcx_(modval, addr_base); break;
+    default: ShouldNotReachHere();
+  }
+}
+
+// CmpxchgX sets condition register to cmpX(current, compare).
+void MacroAssembler::cmpxchg_generic(ConditionRegister flag, Register dest_current_value,
+                                     Register compare_value, Register exchange_value,
+                                     Register addr_base, Register tmp1, Register tmp2,
+                                     int semantics, bool cmpxchgx_hint,
+                                     Register int_flag_success, bool contention_hint, bool weak, int size) {
+  Label retry;
+  Label failed;
+  Label done;
+
+  // Save one branch if result is returned via register and
+  // result register is different from the other ones.
+  bool use_result_reg    = (int_flag_success != noreg);
+  bool preset_result_reg = (int_flag_success != dest_current_value && int_flag_success != compare_value &&
+                            int_flag_success != exchange_value && int_flag_success != addr_base &&
+                            int_flag_success != tmp1 && int_flag_success != tmp2);
+  assert(!weak || flag == CCR0, "weak only supported with CCR0");
+  assert(size == 1 || size == 2 || size == 4, "unsupported");
+
+  if (use_result_reg && preset_result_reg) {
+    li(int_flag_success, 0); // preset (assume cas failed)
+  }
+
+  // Add simple guard in order to reduce risk of starving under high contention (recommended by IBM).
+  if (contention_hint) { // Don't try to reserve if cmp fails.
+    switch (size) {
+      case 1: lbz(dest_current_value, 0, addr_base); extsb(dest_current_value, dest_current_value); break;
+      case 2: lha(dest_current_value, 0, addr_base); break;
+      case 4: lwz(dest_current_value, 0, addr_base); break;
+      default: ShouldNotReachHere();
+    }
+    cmpw(flag, dest_current_value, compare_value);
+    bne(flag, failed);
+  }
+
+  // release/fence semantics
+  if (semantics & MemBarRel) {
+    release();
+  }
+
+  cmpxchg_loop_body(flag, dest_current_value, compare_value, exchange_value, addr_base, tmp1, tmp2,
+                    retry, failed, cmpxchgx_hint, size);
   if (!weak || use_result_reg) {
     if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
       bne_predict_not_taken(CCR0, weak ? failed : retry); // StXcx_ sets CCR0.
@@ -3751,454 +3930,6 @@
   bind(Ldone);
 }
 
-
-// Intrinsics for non-CompactStrings
-
-// Search for a single jchar in an jchar[].
-//
-// Assumes that result differs from all other registers.
-//
-// 'haystack' is the addresses of a jchar-array.
-// 'needle' is either the character to search for or R0.
-// 'needleChar' is the character to search for if 'needle' == R0..
-// 'haycnt' is the length of the haystack. We assume 'haycnt' >=1.
-//
-// Preserves haystack, haycnt, needle and kills all other registers.
-//
-// If needle == R0, we search for the constant needleChar.
-void MacroAssembler::string_indexof_1(Register result, Register haystack, Register haycnt,
-                                      Register needle, jchar needleChar,
-                                      Register tmp1, Register tmp2) {
-
-  assert_different_registers(result, haystack, haycnt, needle, tmp1, tmp2);
-
-  Label L_InnerLoop, L_FinalCheck, L_Found1, L_Found2, L_Found3, L_NotFound, L_End;
-  Register addr = tmp1,
-           ch1 = tmp2,
-           ch2 = R0;
-
-//3:
-   dcbtct(haystack, 0x00);                        // Indicate R/O access to haystack.
-
-   srwi_(tmp2, haycnt, 1);   // Shift right by exact_log2(UNROLL_FACTOR).
-   mr(addr, haystack);
-   beq(CCR0, L_FinalCheck);
-   mtctr(tmp2);              // Move to count register.
-//8:
-  bind(L_InnerLoop);             // Main work horse (2x unrolled search loop).
-   lhz(ch1, 0, addr);        // Load characters from haystack.
-   lhz(ch2, 2, addr);
-   (needle != R0) ? cmpw(CCR0, ch1, needle) : cmplwi(CCR0, ch1, needleChar);
-   (needle != R0) ? cmpw(CCR1, ch2, needle) : cmplwi(CCR1, ch2, needleChar);
-   beq(CCR0, L_Found1);   // Did we find the needle?
-   beq(CCR1, L_Found2);
-   addi(addr, addr, 4);
-   bdnz(L_InnerLoop);
-//16:
-  bind(L_FinalCheck);
-   andi_(R0, haycnt, 1);
-   beq(CCR0, L_NotFound);
-   lhz(ch1, 0, addr);        // One position left at which we have to compare.
-   (needle != R0) ? cmpw(CCR1, ch1, needle) : cmplwi(CCR1, ch1, needleChar);
-   beq(CCR1, L_Found3);
-//21:
-  bind(L_NotFound);
-   li(result, -1);           // Not found.
-   b(L_End);
-
-  bind(L_Found2);
-   addi(addr, addr, 2);
-//24:
-  bind(L_Found1);
-  bind(L_Found3);                  // Return index ...
-   subf(addr, haystack, addr); // relative to haystack,
-   srdi(result, addr, 1);      // in characters.
-  bind(L_End);
-}
-
-
-// Implementation of IndexOf for jchar arrays.
-//
-// The length of haystack and needle are not constant, i.e. passed in a register.
-//
-// Preserves registers haystack, needle.
-// Kills registers haycnt, needlecnt.
-// Assumes that result differs from all other registers.
-// Haystack, needle are the addresses of jchar-arrays.
-// Haycnt, needlecnt are the lengths of them, respectively.
-//
-// Needlecntval must be zero or 15-bit unsigned immediate and > 1.
-void MacroAssembler::string_indexof(Register result, Register haystack, Register haycnt,
-                                    Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval,
-                                    Register tmp1, Register tmp2, Register tmp3, Register tmp4) {
-
-  // Ensure 0<needlecnt<=haycnt in ideal graph as prerequisite!
-  Label L_TooShort, L_Found, L_NotFound, L_End;
-  Register last_addr = haycnt, // Kill haycnt at the beginning.
-           addr      = tmp1,
-           n_start   = tmp2,
-           ch1       = tmp3,
-           ch2       = R0;
-
-  // **************************************************************************************************
-  // Prepare for main loop: optimized for needle count >=2, bail out otherwise.
-  // **************************************************************************************************
-
-//1 (variable) or 3 (const):
-   dcbtct(needle, 0x00);    // Indicate R/O access to str1.
-   dcbtct(haystack, 0x00);  // Indicate R/O access to str2.
-
-  // Compute last haystack addr to use if no match gets found.
-  if (needlecntval == 0) { // variable needlecnt
-//3:
-   subf(ch1, needlecnt, haycnt);      // Last character index to compare is haycnt-needlecnt.
-   addi(addr, haystack, -2);          // Accesses use pre-increment.
-   cmpwi(CCR6, needlecnt, 2);
-   blt(CCR6, L_TooShort);          // Variable needlecnt: handle short needle separately.
-   slwi(ch1, ch1, 1);                 // Scale to number of bytes.
-   lwz(n_start, 0, needle);           // Load first 2 characters of needle.
-   add(last_addr, haystack, ch1);     // Point to last address to compare (haystack+2*(haycnt-needlecnt)).
-   addi(needlecnt, needlecnt, -2);    // Rest of needle.
-  } else { // constant needlecnt
-  guarantee(needlecntval != 1, "IndexOf with single-character needle must be handled separately");
-  assert((needlecntval & 0x7fff) == needlecntval, "wrong immediate");
-//5:
-   addi(ch1, haycnt, -needlecntval);  // Last character index to compare is haycnt-needlecnt.
-   lwz(n_start, 0, needle);           // Load first 2 characters of needle.
-   addi(addr, haystack, -2);          // Accesses use pre-increment.
-   slwi(ch1, ch1, 1);                 // Scale to number of bytes.
-   add(last_addr, haystack, ch1);     // Point to last address to compare (haystack+2*(haycnt-needlecnt)).
-   li(needlecnt, needlecntval-2);     // Rest of needle.
-  }
-
-  // Main Loop (now we have at least 3 characters).
-//11:
-  Label L_OuterLoop, L_InnerLoop, L_FinalCheck, L_Comp1, L_Comp2, L_Comp3;
-  bind(L_OuterLoop); // Search for 1st 2 characters.
-  Register addr_diff = tmp4;
-   subf(addr_diff, addr, last_addr); // Difference between already checked address and last address to check.
-   addi(addr, addr, 2);              // This is the new address we want to use for comparing.
-   srdi_(ch2, addr_diff, 2);
-   beq(CCR0, L_FinalCheck);       // 2 characters left?
-   mtctr(ch2);                       // addr_diff/4
-//16:
-  bind(L_InnerLoop);                // Main work horse (2x unrolled search loop)
-   lwz(ch1, 0, addr);           // Load 2 characters of haystack (ignore alignment).
-   lwz(ch2, 2, addr);
-   cmpw(CCR0, ch1, n_start); // Compare 2 characters (1 would be sufficient but try to reduce branches to CompLoop).
-   cmpw(CCR1, ch2, n_start);
-   beq(CCR0, L_Comp1);       // Did we find the needle start?
-   beq(CCR1, L_Comp2);
-   addi(addr, addr, 4);
-   bdnz(L_InnerLoop);
-//24:
-  bind(L_FinalCheck);
-   rldicl_(addr_diff, addr_diff, 64-1, 63); // Remaining characters not covered by InnerLoop: (addr_diff>>1)&1.
-   beq(CCR0, L_NotFound);
-   lwz(ch1, 0, addr);                       // One position left at which we have to compare.
-   cmpw(CCR1, ch1, n_start);
-   beq(CCR1, L_Comp3);
-//29:
-  bind(L_NotFound);
-   li(result, -1); // not found
-   b(L_End);
-
-
-   // **************************************************************************************************
-   // Special Case: unfortunately, the variable needle case can be called with needlecnt<2
-   // **************************************************************************************************
-//31:
- if ((needlecntval>>1) !=1 ) { // Const needlecnt is 2 or 3? Reduce code size.
-  int nopcnt = 5;
-  if (needlecntval !=0 ) ++nopcnt; // Balance alignment (other case: see below).
-  if (needlecntval == 0) {         // We have to handle these cases separately.
-  Label L_OneCharLoop;
-  bind(L_TooShort);
-   mtctr(haycnt);
-   lhz(n_start, 0, needle);    // First character of needle
-  bind(L_OneCharLoop);
-   lhzu(ch1, 2, addr);
-   cmpw(CCR1, ch1, n_start);
-   beq(CCR1, L_Found);      // Did we find the one character needle?
-   bdnz(L_OneCharLoop);
-   li(result, -1);             // Not found.
-   b(L_End);
-  } // 8 instructions, so no impact on alignment.
-  for (int x = 0; x < nopcnt; ++x) nop();
- }
-
-  // **************************************************************************************************
-  // Regular Case Part II: compare rest of needle (first 2 characters have been compared already)
-  // **************************************************************************************************
-
-  // Compare the rest
-//36 if needlecntval==0, else 37:
-  bind(L_Comp2);
-   addi(addr, addr, 2); // First comparison has failed, 2nd one hit.
-  bind(L_Comp1);            // Addr points to possible needle start.
-  bind(L_Comp3);            // Could have created a copy and use a different return address but saving code size here.
-  if (needlecntval != 2) {  // Const needlecnt==2?
-   if (needlecntval != 3) {
-    if (needlecntval == 0) beq(CCR6, L_Found); // Variable needlecnt==2?
-    Register ind_reg = tmp4;
-    li(ind_reg, 2*2);   // First 2 characters are already compared, use index 2.
-    mtctr(needlecnt);   // Decremented by 2, still > 0.
-//40:
-   Label L_CompLoop;
-   bind(L_CompLoop);
-    lhzx(ch2, needle, ind_reg);
-    lhzx(ch1, addr, ind_reg);
-    cmpw(CCR1, ch1, ch2);
-    bne(CCR1, L_OuterLoop);
-    addi(ind_reg, ind_reg, 2);
-    bdnz(L_CompLoop);
-   } else { // No loop required if there's only one needle character left.
-    lhz(ch2, 2*2, needle);
-    lhz(ch1, 2*2, addr);
-    cmpw(CCR1, ch1, ch2);
-    bne(CCR1, L_OuterLoop);
-   }
-  }
-  // Return index ...
-//46:
-  bind(L_Found);
-   subf(addr, haystack, addr); // relative to haystack, ...
-   srdi(result, addr, 1);      // in characters.
-//48:
-  bind(L_End);
-}
-
-// Implementation of Compare for jchar arrays.
-//
-// Kills the registers str1, str2, cnt1, cnt2.
-// Kills cr0, ctr.
-// Assumes that result differes from the input registers.
-void MacroAssembler::string_compare(Register str1_reg, Register str2_reg, Register cnt1_reg, Register cnt2_reg,
-                                    Register result_reg, Register tmp_reg) {
-   assert_different_registers(result_reg, str1_reg, str2_reg, cnt1_reg, cnt2_reg, tmp_reg);
-
-   Label Ldone, Lslow_case, Lslow_loop, Lfast_loop;
-   Register cnt_diff = R0,
-            limit_reg = cnt1_reg,
-            chr1_reg = result_reg,
-            chr2_reg = cnt2_reg,
-            addr_diff = str2_reg;
-
-   // 'cnt_reg' contains the number of characters in the string's character array for the
-   // pre-CompactStrings strings implementation and the number of bytes in the string's
-   // byte array for the CompactStrings strings implementation.
-   const int HAS_COMPACT_STRING = java_lang_String::has_coder_field() ? 1 : 0; // '1' = byte array, '0' = char array
-
-   // Offset 0 should be 32 byte aligned.
-//-6:
-    srawi(cnt1_reg, cnt1_reg, HAS_COMPACT_STRING);
-    srawi(cnt2_reg, cnt2_reg, HAS_COMPACT_STRING);
-//-4:
-    dcbtct(str1_reg, 0x00);  // Indicate R/O access to str1.
-    dcbtct(str2_reg, 0x00);  // Indicate R/O access to str2.
-//-2:
-   // Compute min(cnt1, cnt2) and check if 0 (bail out if we don't need to compare characters).
-    subf(result_reg, cnt2_reg, cnt1_reg);  // difference between cnt1/2
-    subf_(addr_diff, str1_reg, str2_reg);  // alias?
-    beq(CCR0, Ldone);                   // return cnt difference if both ones are identical
-    srawi(limit_reg, result_reg, 31);      // generate signmask (cnt1/2 must be non-negative so cnt_diff can't overflow)
-    mr(cnt_diff, result_reg);
-    andr(limit_reg, result_reg, limit_reg); // difference or zero (negative): cnt1<cnt2 ? cnt1-cnt2 : 0
-    add_(limit_reg, cnt2_reg, limit_reg);  // min(cnt1, cnt2)==0?
-    beq(CCR0, Ldone);                   // return cnt difference if one has 0 length
-
-    lhz(chr1_reg, 0, str1_reg);            // optional: early out if first characters mismatch
-    lhzx(chr2_reg, str1_reg, addr_diff);   // optional: early out if first characters mismatch
-    addi(tmp_reg, limit_reg, -1);          // min(cnt1, cnt2)-1
-    subf_(result_reg, chr2_reg, chr1_reg); // optional: early out if first characters mismatch
-    bne(CCR0, Ldone);                   // optional: early out if first characters mismatch
-
-   // Set loop counter by scaling down tmp_reg
-    srawi_(chr2_reg, tmp_reg, exact_log2(4)); // (min(cnt1, cnt2)-1)/4
-    ble(CCR0, Lslow_case);                 // need >4 characters for fast loop
-    andi(limit_reg, tmp_reg, 4-1);            // remaining characters
-
-   // Adapt str1_reg str2_reg for the first loop iteration
-    mtctr(chr2_reg);                 // (min(cnt1, cnt2)-1)/4
-    addi(limit_reg, limit_reg, 4+1); // compare last 5-8 characters in slow_case if mismatch found in fast_loop
-//16:
-   // Compare the rest of the characters
-   bind(Lfast_loop);
-    ld(chr1_reg, 0, str1_reg);
-    ldx(chr2_reg, str1_reg, addr_diff);
-    cmpd(CCR0, chr2_reg, chr1_reg);
-    bne(CCR0, Lslow_case); // return chr1_reg
-    addi(str1_reg, str1_reg, 4*2);
-    bdnz(Lfast_loop);
-    addi(limit_reg, limit_reg, -4); // no mismatch found in fast_loop, only 1-4 characters missing
-//23:
-   bind(Lslow_case);
-    mtctr(limit_reg);
-//24:
-   bind(Lslow_loop);
-    lhz(chr1_reg, 0, str1_reg);
-    lhzx(chr2_reg, str1_reg, addr_diff);
-    subf_(result_reg, chr2_reg, chr1_reg);
-    bne(CCR0, Ldone); // return chr1_reg
-    addi(str1_reg, str1_reg, 1*2);
-    bdnz(Lslow_loop);
-//30:
-   // If strings are equal up to min length, return the length difference.
-    mr(result_reg, cnt_diff);
-    nop(); // alignment
-//32:
-   // Otherwise, return the difference between the first mismatched chars.
-   bind(Ldone);
-}
-
-
-// Compare char[] arrays.
-//
-// str1_reg   USE only
-// str2_reg   USE only
-// cnt_reg    USE_DEF, due to tmp reg shortage
-// result_reg DEF only, might compromise USE only registers
-void MacroAssembler::char_arrays_equals(Register str1_reg, Register str2_reg, Register cnt_reg, Register result_reg,
-                                        Register tmp1_reg, Register tmp2_reg, Register tmp3_reg, Register tmp4_reg,
-                                        Register tmp5_reg) {
-
-  // Str1 may be the same register as str2 which can occur e.g. after scalar replacement.
-  assert_different_registers(result_reg, str1_reg, cnt_reg, tmp1_reg, tmp2_reg, tmp3_reg, tmp4_reg, tmp5_reg);
-  assert_different_registers(result_reg, str2_reg, cnt_reg, tmp1_reg, tmp2_reg, tmp3_reg, tmp4_reg, tmp5_reg);
-
-  // Offset 0 should be 32 byte aligned.
-  Label Linit_cbc, Lcbc, Lloop, Ldone_true, Ldone_false;
-  Register index_reg = tmp5_reg;
-  Register cbc_iter  = tmp4_reg;
-
-  // 'cnt_reg' contains the number of characters in the string's character array for the
-  // pre-CompactStrings strings implementation and the number of bytes in the string's
-  // byte array for the CompactStrings strings implementation.
-  const int HAS_COMPACT_STRING = java_lang_String::has_coder_field() ? 1 : 0; // '1' = byte array, '0' = char array
-
-//-1:
-  dcbtct(str1_reg, 0x00);  // Indicate R/O access to str1.
-  dcbtct(str2_reg, 0x00);  // Indicate R/O access to str2.
-//1:
-  // cbc_iter: remaining characters after the '4 java characters per iteration' loop.
-  rlwinm(cbc_iter, cnt_reg, 32 - HAS_COMPACT_STRING, 30, 31); // (cnt_reg % (HAS_COMPACT_STRING ? 8 : 4)) >> HAS_COMPACT_STRING
-  li(index_reg, 0); // init
-  li(result_reg, 0); // assume false
-  // tmp2_reg: units of 4 java characters (i.e. 8 bytes) per iteration (main loop).
-  srwi_(tmp2_reg, cnt_reg, exact_log2(4 << HAS_COMPACT_STRING)); // cnt_reg / (HAS_COMPACT_STRING ? 8 : 4)
-
-  cmpwi(CCR1, cbc_iter, 0);             // CCR1 = (cbc_iter==0)
-  beq(CCR0, Linit_cbc);                 // too short
-    mtctr(tmp2_reg);
-//8:
-    bind(Lloop);
-      ldx(tmp1_reg, str1_reg, index_reg);
-      ldx(tmp2_reg, str2_reg, index_reg);
-      cmpd(CCR0, tmp1_reg, tmp2_reg);
-      bne(CCR0, Ldone_false);  // Unequal char pair found -> done.
-      addi(index_reg, index_reg, 4*sizeof(jchar));
-      bdnz(Lloop);
-//14:
-  bind(Linit_cbc);
-  beq(CCR1, Ldone_true);
-    mtctr(cbc_iter);
-//16:
-    bind(Lcbc);
-      lhzx(tmp1_reg, str1_reg, index_reg);
-      lhzx(tmp2_reg, str2_reg, index_reg);
-      cmpw(CCR0, tmp1_reg, tmp2_reg);
-      bne(CCR0, Ldone_false);  // Unequal char pair found -> done.
-      addi(index_reg, index_reg, 1*sizeof(jchar));
-      bdnz(Lcbc);
-    nop();
-  bind(Ldone_true);
-  li(result_reg, 1);
-//24:
-  bind(Ldone_false);
-}
-
-
-void MacroAssembler::char_arrays_equalsImm(Register str1_reg, Register str2_reg, int cntval, Register result_reg,
-                                           Register tmp1_reg, Register tmp2_reg) {
-  // Str1 may be the same register as str2 which can occur e.g. after scalar replacement.
-  assert_different_registers(result_reg, str1_reg, tmp1_reg, tmp2_reg);
-  assert_different_registers(result_reg, str2_reg, tmp1_reg, tmp2_reg);
-  assert(sizeof(jchar) == 2, "must be");
-  assert(cntval >= 0 && ((cntval & 0x7fff) == cntval), "wrong immediate");
-
-  // 'cntval' contains the number of characters in the string's character array for the
-  // pre-CompactStrings strings implementation and the number of bytes in the string's
-  // byte array for the CompactStrings strings implementation.
-  cntval >>= (java_lang_String::has_coder_field() ? 1 : 0); // '1' = byte array strings, '0' = char array strings
-
-  Label Ldone_false;
-
-  if (cntval < 16) { // short case
-    if (cntval != 0) li(result_reg, 0); // assume false
-
-    const int num_bytes = cntval*sizeof(jchar);
-    int index = 0;
-    for (int next_index; (next_index = index + 8) <= num_bytes; index = next_index) {
-      ld(tmp1_reg, index, str1_reg);
-      ld(tmp2_reg, index, str2_reg);
-      cmpd(CCR0, tmp1_reg, tmp2_reg);
-      bne(CCR0, Ldone_false);
-    }
-    if (cntval & 2) {
-      lwz(tmp1_reg, index, str1_reg);
-      lwz(tmp2_reg, index, str2_reg);
-      cmpw(CCR0, tmp1_reg, tmp2_reg);
-      bne(CCR0, Ldone_false);
-      index += 4;
-    }
-    if (cntval & 1) {
-      lhz(tmp1_reg, index, str1_reg);
-      lhz(tmp2_reg, index, str2_reg);
-      cmpw(CCR0, tmp1_reg, tmp2_reg);
-      bne(CCR0, Ldone_false);
-    }
-    // fallthrough: true
-  } else {
-    Label Lloop;
-    Register index_reg = tmp1_reg;
-    const int loopcnt = cntval/4;
-    assert(loopcnt > 0, "must be");
-    // Offset 0 should be 32 byte aligned.
-    //2:
-    dcbtct(str1_reg, 0x00);  // Indicate R/O access to str1.
-    dcbtct(str2_reg, 0x00);  // Indicate R/O access to str2.
-    li(tmp2_reg, loopcnt);
-    li(index_reg, 0); // init
-    li(result_reg, 0); // assume false
-    mtctr(tmp2_reg);
-    //8:
-    bind(Lloop);
-    ldx(R0, str1_reg, index_reg);
-    ldx(tmp2_reg, str2_reg, index_reg);
-    cmpd(CCR0, R0, tmp2_reg);
-    bne(CCR0, Ldone_false);  // Unequal char pair found -> done.
-    addi(index_reg, index_reg, 4*sizeof(jchar));
-    bdnz(Lloop);
-    //14:
-    if (cntval & 2) {
-      lwzx(R0, str1_reg, index_reg);
-      lwzx(tmp2_reg, str2_reg, index_reg);
-      cmpw(CCR0, R0, tmp2_reg);
-      bne(CCR0, Ldone_false);
-      if (cntval & 1) addi(index_reg, index_reg, 2*sizeof(jchar));
-    }
-    if (cntval & 1) {
-      lhzx(R0, str1_reg, index_reg);
-      lhzx(tmp2_reg, str2_reg, index_reg);
-      cmpw(CCR0, R0, tmp2_reg);
-      bne(CCR0, Ldone_false);
-    }
-    // fallthru: true
-  }
-  li(result_reg, 1);
-  bind(Ldone_false);
-}
-
 #endif // Compiler2
 
 // Helpers for Intrinsic Emitters
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Fri Jul 01 16:50:34 2016 -0700
@@ -431,10 +431,81 @@
     MemBarAcq  = 2,
     MemBarFenceAfter = 4 // use powers of 2
   };
+ private:
+  // Helper functions for word/sub-word atomics.
+  void atomic_get_and_modify_generic(Register dest_current_value, Register exchange_value,
+                                     Register addr_base, Register tmp1, Register tmp2, Register tmp3,
+                                     bool cmpxchgx_hint, bool is_add, int size);
+  void cmpxchg_loop_body(ConditionRegister flag, Register dest_current_value,
+                         Register compare_value, Register exchange_value,
+                         Register addr_base, Register tmp1, Register tmp2,
+                         Label &retry, Label &failed, bool cmpxchgx_hint, int size);
+  void cmpxchg_generic(ConditionRegister flag,
+                       Register dest_current_value, Register compare_value, Register exchange_value, Register addr_base,
+                       Register tmp1, Register tmp2,
+                       int semantics, bool cmpxchgx_hint, Register int_flag_success, bool contention_hint, bool weak, int size);
+ public:
+  // Temps and addr_base are killed if processor does not support Power 8 instructions.
+  // Result will be sign extended.
+  void getandsetb(Register dest_current_value, Register exchange_value, Register addr_base,
+                  Register tmp1, Register tmp2, Register tmp3, bool cmpxchgx_hint) {
+    atomic_get_and_modify_generic(dest_current_value, exchange_value, addr_base, tmp1, tmp2, tmp3, cmpxchgx_hint, false, 1);
+  }
+  // Temps and addr_base are killed if processor does not support Power 8 instructions.
+  // Result will be sign extended.
+  void getandseth(Register dest_current_value, Register exchange_value, Register addr_base,
+                  Register tmp1, Register tmp2, Register tmp3, bool cmpxchgx_hint) {
+    atomic_get_and_modify_generic(dest_current_value, exchange_value, addr_base, tmp1, tmp2, tmp3, cmpxchgx_hint, false, 2);
+  }
+  void getandsetw(Register dest_current_value, Register exchange_value, Register addr_base,
+                  bool cmpxchgx_hint) {
+    atomic_get_and_modify_generic(dest_current_value, exchange_value, addr_base, noreg, noreg, noreg, cmpxchgx_hint, false, 4);
+  }
+  void getandsetd(Register dest_current_value, Register exchange_value, Register addr_base,
+                  bool cmpxchgx_hint);
+  // tmp2/3 and addr_base are killed if processor does not support Power 8 instructions (tmp1 is always needed).
+  // Result will be sign extended.
+  void getandaddb(Register dest_current_value, Register inc_value, Register addr_base,
+                  Register tmp1, Register tmp2, Register tmp3, bool cmpxchgx_hint) {
+    atomic_get_and_modify_generic(dest_current_value, inc_value, addr_base, tmp1, tmp2, tmp3, cmpxchgx_hint, true, 1);
+  }
+  // tmp2/3 and addr_base are killed if processor does not support Power 8 instructions (tmp1 is always needed).
+  // Result will be sign extended.
+  void getandaddh(Register dest_current_value, Register inc_value, Register addr_base,
+                  Register tmp1, Register tmp2, Register tmp3, bool cmpxchgx_hint) {
+    atomic_get_and_modify_generic(dest_current_value, inc_value, addr_base, tmp1, tmp2, tmp3, cmpxchgx_hint, true, 2);
+  }
+  void getandaddw(Register dest_current_value, Register inc_value, Register addr_base,
+                  Register tmp1, bool cmpxchgx_hint) {
+    atomic_get_and_modify_generic(dest_current_value, inc_value, addr_base, tmp1, noreg, noreg, cmpxchgx_hint, true, 4);
+  }
+  void getandaddd(Register dest_current_value, Register exchange_value, Register addr_base,
+                  Register tmp, bool cmpxchgx_hint);
+  // Temps, addr_base and exchange_value are killed if processor does not support Power 8 instructions.
+  // compare_value must be at least 32 bit sign extended. Result will be sign extended.
+  void cmpxchgb(ConditionRegister flag,
+                Register dest_current_value, Register compare_value, Register exchange_value, Register addr_base,
+                Register tmp1, Register tmp2, int semantics, bool cmpxchgx_hint = false,
+                Register int_flag_success = noreg, bool contention_hint = false, bool weak = false) {
+    cmpxchg_generic(flag, dest_current_value, compare_value, exchange_value, addr_base, tmp1, tmp2,
+                    semantics, cmpxchgx_hint, int_flag_success, contention_hint, weak, 1);
+  }
+  // Temps, addr_base and exchange_value are killed if processor does not support Power 8 instructions.
+  // compare_value must be at least 32 bit sign extended. Result will be sign extended.
+  void cmpxchgh(ConditionRegister flag,
+                Register dest_current_value, Register compare_value, Register exchange_value, Register addr_base,
+                Register tmp1, Register tmp2, int semantics, bool cmpxchgx_hint = false,
+                Register int_flag_success = noreg, bool contention_hint = false, bool weak = false) {
+    cmpxchg_generic(flag, dest_current_value, compare_value, exchange_value, addr_base, tmp1, tmp2,
+                    semantics, cmpxchgx_hint, int_flag_success, contention_hint, weak, 2);
+  }
   void cmpxchgw(ConditionRegister flag,
                 Register dest_current_value, Register compare_value, Register exchange_value, Register addr_base,
                 int semantics, bool cmpxchgx_hint = false,
-                Register int_flag_success = noreg, bool contention_hint = false, bool weak = false);
+                Register int_flag_success = noreg, bool contention_hint = false, bool weak = false) {
+    cmpxchg_generic(flag, dest_current_value, compare_value, exchange_value, addr_base, noreg, noreg,
+                    semantics, cmpxchgx_hint, int_flag_success, contention_hint, weak, 4);
+  }
   void cmpxchgd(ConditionRegister flag,
                 Register dest_current_value, RegisterOrConstant compare_value, Register exchange_value,
                 Register addr_base, int semantics, bool cmpxchgx_hint = false,
@@ -717,23 +788,6 @@
                            Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte);
 
   void has_negatives(Register src, Register cnt, Register result, Register tmp1, Register tmp2);
-
-  // Intrinsics for non-CompactStrings
-  // Needle of length 1.
-  void string_indexof_1(Register result, Register haystack, Register haycnt,
-                        Register needle, jchar needleChar,
-                        Register tmp1, Register tmp2);
-  // General indexof, eventually with constant needle length.
-  void string_indexof(Register result, Register haystack, Register haycnt,
-                      Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval,
-                      Register tmp1, Register tmp2, Register tmp3, Register tmp4);
-  void string_compare(Register str1_reg, Register str2_reg, Register cnt1_reg, Register cnt2_reg,
-                      Register result_reg, Register tmp_reg);
-  void char_arrays_equals(Register str1_reg, Register str2_reg, Register cnt_reg, Register result_reg,
-                          Register tmp1_reg, Register tmp2_reg, Register tmp3_reg, Register tmp4_reg,
-                          Register tmp5_reg);
-  void char_arrays_equalsImm(Register str1_reg, Register str2_reg, int cntval, Register result_reg,
-                             Register tmp1_reg, Register tmp2_reg);
 #endif
 
   // Emitters for BigInteger.multiplyToLen intrinsic.
--- a/hotspot/src/cpu/ppc/vm/ppc.ad	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad	Fri Jul 01 16:50:34 2016 -0700
@@ -965,41 +965,9 @@
 // is the number of bytes (not instructions) which will be inserted before
 // the instruction. The padding must match the size of a NOP instruction.
 
-int string_indexOf_imm1_charNode::compute_padding(int current_offset) const {
-  return (3*4-current_offset)&31;  // see MacroAssembler::string_indexof_1
-}
-
-int string_indexOf_imm1Node::compute_padding(int current_offset) const {
-  return (3*4-current_offset)&31;  // see MacroAssembler::string_indexof_1
-}
-
-int string_indexOfCharNode::compute_padding(int current_offset) const {
-  return (3*4-current_offset)&31;  // see MacroAssembler::string_indexof_1
-}
-
-int string_indexOf_immNode::compute_padding(int current_offset) const {
-  return (3*4-current_offset)&31;  // see MacroAssembler::string_indexof(constant needlecount)
-}
-
-int string_indexOfNode::compute_padding(int current_offset) const {
-  return (1*4-current_offset)&31;  // see MacroAssembler::string_indexof(variable needlecount)
-}
-
-int string_compareNode::compute_padding(int current_offset) const {
-  return (2*4-current_offset)&31;  // see MacroAssembler::string_compare
-}
-
-int string_equals_immNode::compute_padding(int current_offset) const {
-  if (opnd_array(3)->constant() < 16) return 0; // For strlen < 16 no nops because loop completely unrolled
-  return (2*4-current_offset)&31;               // Genral case - see MacroAssembler::char_arrays_equalsImm
-}
-
-int string_equalsNode::compute_padding(int current_offset) const {
-  return (7*4-current_offset)&31;  // see MacroAssembler::char_arrays_equals
-}
-
 int inlineCallClearArrayNode::compute_padding(int current_offset) const {
-  return (2*4-current_offset)&31;  // see MacroAssembler::clear_memory_doubleword
+  int desired_padding = (2*4-current_offset)&31; // see MacroAssembler::clear_memory_doubleword
+  return (desired_padding <= 3*4) ? desired_padding : 0;
 }
 
 //=============================================================================
@@ -3064,121 +3032,6 @@
     __ bind(done);
   %}
 
-  // New atomics.
-  enc_class enc_GetAndAddI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src) %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-
-    MacroAssembler _masm(&cbuf);
-    Register Rtmp   = R0;
-    Register Rres   = $res$$Register;
-    Register Rsrc   = $src$$Register;
-    Register Rptr   = $mem_ptr$$Register;
-    bool RegCollision = (Rres == Rsrc) || (Rres == Rptr);
-    Register Rold   = RegCollision ? Rtmp : Rres;
-
-    Label Lretry;
-    __ bind(Lretry);
-    __ lwarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update());
-    __ add(Rtmp, Rsrc, Rold);
-    __ stwcx_(Rtmp, Rptr);
-    if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
-      __ bne_predict_not_taken(CCR0, Lretry);
-    } else {
-      __ bne(                  CCR0, Lretry);
-    }
-    if (RegCollision) __ subf(Rres, Rsrc, Rtmp);
-    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
-      __ isync();
-    } else {
-      __ sync();
-    }
-  %}
-
-  enc_class enc_GetAndAddL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src) %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-
-    MacroAssembler _masm(&cbuf);
-    Register Rtmp   = R0;
-    Register Rres   = $res$$Register;
-    Register Rsrc   = $src$$Register;
-    Register Rptr   = $mem_ptr$$Register;
-    bool RegCollision = (Rres == Rsrc) || (Rres == Rptr);
-    Register Rold   = RegCollision ? Rtmp : Rres;
-
-    Label Lretry;
-    __ bind(Lretry);
-    __ ldarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update());
-    __ add(Rtmp, Rsrc, Rold);
-    __ stdcx_(Rtmp, Rptr);
-    if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
-      __ bne_predict_not_taken(CCR0, Lretry);
-    } else {
-      __ bne(                  CCR0, Lretry);
-    }
-    if (RegCollision) __ subf(Rres, Rsrc, Rtmp);
-    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
-      __ isync();
-    } else {
-      __ sync();
-    }
-  %}
-
-  enc_class enc_GetAndSetI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src) %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-
-    MacroAssembler _masm(&cbuf);
-    Register Rtmp   = R0;
-    Register Rres   = $res$$Register;
-    Register Rsrc   = $src$$Register;
-    Register Rptr   = $mem_ptr$$Register;
-    bool RegCollision = (Rres == Rsrc) || (Rres == Rptr);
-    Register Rold   = RegCollision ? Rtmp : Rres;
-
-    Label Lretry;
-    __ bind(Lretry);
-    __ lwarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update());
-    __ stwcx_(Rsrc, Rptr);
-    if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
-      __ bne_predict_not_taken(CCR0, Lretry);
-    } else {
-      __ bne(                  CCR0, Lretry);
-    }
-    if (RegCollision) __ mr(Rres, Rtmp);
-    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
-      __ isync();
-    } else {
-      __ sync();
-    }
-  %}
-
-  enc_class enc_GetAndSetL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src) %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-
-    MacroAssembler _masm(&cbuf);
-    Register Rtmp   = R0;
-    Register Rres   = $res$$Register;
-    Register Rsrc   = $src$$Register;
-    Register Rptr   = $mem_ptr$$Register;
-    bool RegCollision = (Rres == Rsrc) || (Rres == Rptr);
-    Register Rold   = RegCollision ? Rtmp : Rres;
-
-    Label Lretry;
-    __ bind(Lretry);
-    __ ldarx(Rold, Rptr, MacroAssembler::cmpxchgx_hint_atomic_update());
-    __ stdcx_(Rsrc, Rptr);
-    if (UseStaticBranchPredictionInCompareAndSwapPPC64) {
-      __ bne_predict_not_taken(CCR0, Lretry);
-    } else {
-      __ bne(                  CCR0, Lretry);
-    }
-    if (RegCollision) __ mr(Rres, Rtmp);
-    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
-      __ isync();
-    } else {
-      __ sync();
-    }
-  %}
-
   // This enc_class is needed so that scheduler gets proper
   // input mapping for latency computation.
   enc_class enc_andc(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
@@ -5416,7 +5269,7 @@
 %}
 
 // Match loading integer and casting it to long.
-instruct loadI2L(iRegLdst dst, memory mem) %{
+instruct loadI2L(iRegLdst dst, memoryAlg4 mem) %{
   match(Set dst (ConvI2L (LoadI mem)));
   predicate(_kids[0]->_leaf->as_Load()->is_unordered());
   ins_cost(MEMORY_REF_COST);
@@ -5432,7 +5285,7 @@
 %}
 
 // Match loading integer and casting it to long - acquire.
-instruct loadI2L_ac(iRegLdst dst, memory mem) %{
+instruct loadI2L_ac(iRegLdst dst, memoryAlg4 mem) %{
   match(Set dst (ConvI2L (LoadI mem)));
   ins_cost(3*MEMORY_REF_COST);
 
@@ -7575,11 +7428,90 @@
 
 // Strong versions:
 
+instruct compareAndSwapB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndSwapB mem_ptr (Binary src1 src2)));
+  predicate(VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                $res$$Register, true);
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndSwapB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndSwapB mem_ptr (Binary src1 src2)));
+  predicate(!VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                $res$$Register, true);
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndSwapS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndSwapS mem_ptr (Binary src1 src2)));
+  predicate(VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                $res$$Register, true);
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndSwapS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndSwapS mem_ptr (Binary src1 src2)));
+  predicate(!VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                $res$$Register, true);
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct compareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
   match(Set res (CompareAndSwapI mem_ptr (Binary src1 src2)));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7597,9 +7529,8 @@
 
 instruct compareAndSwapN_regP_regN_regN(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
   match(Set res (CompareAndSwapN mem_ptr (Binary src1 src2)));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7617,9 +7548,8 @@
 
 instruct compareAndSwapL_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, iRegLsrc src1, iRegLsrc src2, flagsRegCR0 cr0) %{
   match(Set res (CompareAndSwapL mem_ptr (Binary src1 src2)));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7637,9 +7567,8 @@
 
 instruct compareAndSwapP_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
   match(Set res (CompareAndSwapP mem_ptr (Binary src1 src2)));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7657,12 +7586,131 @@
 
 // Weak versions:
 
+instruct weakCompareAndSwapB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (WeakCompareAndSwapB mem_ptr (Binary src1 src2)));
+  predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "weak CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                MacroAssembler::MemBarNone,
+                MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct weakCompareAndSwapB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{
+  match(Set res (WeakCompareAndSwapB mem_ptr (Binary src1 src2)));
+  predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && !VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "weak CMPXCHGB $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register,
+                MacroAssembler::MemBarNone,
+                MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct weakCompareAndSwapB_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (WeakCompareAndSwapB mem_ptr (Binary src1 src2)));
+  predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "weak CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter,
+                MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct weakCompareAndSwapB4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{
+  match(Set res (WeakCompareAndSwapB mem_ptr (Binary src1 src2)));
+  predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && !VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "weak CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register,
+                support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter,
+                MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct weakCompareAndSwapS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (WeakCompareAndSwapS mem_ptr (Binary src1 src2)));
+  predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "weak CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                MacroAssembler::MemBarNone,
+                MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct weakCompareAndSwapS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{
+  match(Set res (WeakCompareAndSwapS mem_ptr (Binary src1 src2)));
+  predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && !VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "weak CMPXCHGH $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register,
+                MacroAssembler::MemBarNone,
+                MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct weakCompareAndSwapS_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (WeakCompareAndSwapS mem_ptr (Binary src1 src2)));
+  predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "weak CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter,
+                MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct weakCompareAndSwapS4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, iRegIdst tmp2, flagsRegCR0 cr0) %{
+  match(Set res (WeakCompareAndSwapS mem_ptr (Binary src1 src2)));
+  predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && !VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0); // TEMP_DEF to avoid jump
+  format %{ "weak CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as bool" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, $tmp2$$Register,
+                support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter,
+                MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, true, /*weak*/ true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct weakCompareAndSwapI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
   match(Set res (WeakCompareAndSwapI mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "weak CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7676,9 +7724,8 @@
 instruct weakCompareAndSwapI_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
   match(Set res (WeakCompareAndSwapI mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "weak CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7694,9 +7741,8 @@
 instruct weakCompareAndSwapN_regP_regN_regN(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
   match(Set res (WeakCompareAndSwapN mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "weak CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7710,9 +7756,8 @@
 instruct weakCompareAndSwapN_acq_regP_regN_regN(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
   match(Set res (WeakCompareAndSwapN mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "weak CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7728,9 +7773,8 @@
 instruct weakCompareAndSwapL_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, iRegLsrc src1, iRegLsrc src2, flagsRegCR0 cr0) %{
   match(Set res (WeakCompareAndSwapL mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "weak CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7745,9 +7789,8 @@
 instruct weakCompareAndSwapL_acq_regP_regL_regL(iRegIdst res, iRegPdst mem_ptr, iRegLsrc src1, iRegLsrc src2, flagsRegCR0 cr0) %{
   match(Set res (WeakCompareAndSwapL mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "weak CMPXCHGD acq $res, $mem_ptr, $src1, $src2; as bool" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7763,9 +7806,8 @@
 instruct weakCompareAndSwapP_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
   match(Set res (WeakCompareAndSwapP mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "weak CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7779,9 +7821,8 @@
 instruct weakCompareAndSwapP_acq_regP_regP_regP(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
   match(Set res (WeakCompareAndSwapP mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
   format %{ "weak CMPXCHGD acq $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7796,12 +7837,155 @@
 
 // CompareAndExchange
 
+instruct compareAndExchangeB_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndExchangeB mem_ptr (Binary src1 src2)));
+  predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0);
+  format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as int" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                noreg, true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndExchangeB4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndExchangeB mem_ptr (Binary src1 src2)));
+  predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && !VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0);
+  format %{ "CMPXCHGB $res, $mem_ptr, $src1, $src2; as int" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                noreg, true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndExchangeB_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndExchangeB mem_ptr (Binary src1 src2)));
+  predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0);
+  format %{ "CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as int" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                noreg, true);
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that.
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndExchangeB4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndExchangeB mem_ptr (Binary src1 src2)));
+  predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && !VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0);
+  format %{ "CMPXCHGB acq $res, $mem_ptr, $src1, $src2; as int" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgb(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                noreg, true);
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that.
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndExchangeS_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndExchangeS mem_ptr (Binary src1 src2)));
+  predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0);
+  format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as int" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                noreg, true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndExchangeS4_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndExchangeS mem_ptr (Binary src1 src2)));
+  predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst && !VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0);
+  format %{ "CMPXCHGH $res, $mem_ptr, $src1, $src2; as int" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                noreg, true);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndExchangeS_acq_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndExchangeS mem_ptr (Binary src1 src2)));
+  predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0);
+  format %{ "CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as int" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, noreg, noreg,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                noreg, true);
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that.
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct compareAndExchangeS4_acq_regP_regI_regI(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src1, rarg4RegI src2, iRegIdst tmp1, flagsRegCR0 cr0) %{
+  match(Set res (CompareAndExchangeS mem_ptr (Binary src1 src2)));
+  predicate((((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst) && !VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL src2, USE_KILL mem_ptr, TEMP tmp1, TEMP cr0);
+  format %{ "CMPXCHGH acq $res, $mem_ptr, $src1, $src2; as int" %}
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
+    // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+    __ cmpxchgh(CCR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register, $tmp1$$Register, R0,
+                MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                noreg, true);
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that.
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct compareAndExchangeI_regP_regI_regI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src1, iRegIsrc src2, flagsRegCR0 cr0) %{
   match(Set res (CompareAndExchangeI mem_ptr (Binary src1 src2)));
   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
   effect(TEMP_DEF res, TEMP cr0);
   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as int" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7817,7 +8001,6 @@
   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
   effect(TEMP_DEF res, TEMP cr0);
   format %{ "CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as int" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7839,7 +8022,6 @@
   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
   effect(TEMP_DEF res, TEMP cr0);
   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as narrow oop" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7855,7 +8037,6 @@
   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
   effect(TEMP_DEF res, TEMP cr0);
   format %{ "CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as narrow oop" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7877,7 +8058,6 @@
   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
   effect(TEMP_DEF res, TEMP cr0);
   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as long" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7893,7 +8073,6 @@
   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
   effect(TEMP_DEF res, TEMP cr0);
   format %{ "CMPXCHGD acq $res, $mem_ptr, $src1, $src2; as long" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7915,7 +8094,6 @@
   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
   effect(TEMP_DEF res, TEMP cr0);
   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as ptr; ptr" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7931,7 +8109,6 @@
   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
   effect(TEMP_DEF res, TEMP cr0);
   format %{ "CMPXCHGD acq $res, $mem_ptr, $src1, $src2; as ptr; ptr" %}
-  // Variable size: instruction count smaller if regs are disjoint.
   ins_encode %{
     // TODO: PPC port $archOpcode(ppc64Opcode_compound);
     // CmpxchgX sets CCR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
@@ -7950,57 +8127,235 @@
 
 // Special RMW
 
+instruct getAndAddB(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{
+  match(Set res (GetAndAddB mem_ptr src));
+  predicate(VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0);
+  format %{ "GetAndAddB $res, $mem_ptr, $src" %}
+  ins_encode %{
+    __ getandaddb($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  R0, noreg, noreg, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct getAndAddB4(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src, iRegIsrc tmp1, iRegIsrc tmp2, flagsRegCR0 cr0) %{
+  match(Set res (GetAndAddB mem_ptr src));
+  predicate(!VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0);
+  format %{ "GetAndAddB $res, $mem_ptr, $src" %}
+  ins_encode %{
+    __ getandaddb($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  R0, $tmp1$$Register, $tmp2$$Register, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct getAndAddS(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{
+  match(Set res (GetAndAddS mem_ptr src));
+  predicate(VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0);
+  format %{ "GetAndAddS $res, $mem_ptr, $src" %}
+  ins_encode %{
+    __ getandaddh($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  R0, noreg, noreg, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct getAndAddS4(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src, iRegIsrc tmp1, iRegIsrc tmp2, flagsRegCR0 cr0) %{
+  match(Set res (GetAndAddS mem_ptr src));
+  predicate(!VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0);
+  format %{ "GetAndAddS $res, $mem_ptr, $src" %}
+  ins_encode %{
+    __ getandaddh($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  R0, $tmp1$$Register, $tmp2$$Register, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 instruct getAndAddI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{
   match(Set res (GetAndAddI mem_ptr src));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0);
   format %{ "GetAndAddI $res, $mem_ptr, $src" %}
-  // Variable size: instruction count smaller if regs are disjoint.
-  ins_encode( enc_GetAndAddI(res, mem_ptr, src) );
+  ins_encode %{
+    __ getandaddw($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  R0, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
   ins_pipe(pipe_class_default);
 %}
 
 instruct getAndAddL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src, flagsRegCR0 cr0) %{
   match(Set res (GetAndAddL mem_ptr src));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0);
   format %{ "GetAndAddL $res, $mem_ptr, $src" %}
-  // Variable size: instruction count smaller if regs are disjoint.
-  ins_encode( enc_GetAndAddL(res, mem_ptr, src) );
+  ins_encode %{
+    __ getandaddd($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  R0, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct getAndSetB(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{
+  match(Set res (GetAndSetB mem_ptr src));
+  predicate(VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0);
+  format %{ "GetAndSetB $res, $mem_ptr, $src" %}
+  ins_encode %{
+    __ getandsetb($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  noreg, noreg, noreg, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct getAndSetB4(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src, iRegIsrc tmp1, iRegIsrc tmp2, flagsRegCR0 cr0) %{
+  match(Set res (GetAndSetB mem_ptr src));
+  predicate(!VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0);
+  format %{ "GetAndSetB $res, $mem_ptr, $src" %}
+  ins_encode %{
+    __ getandsetb($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  R0, $tmp1$$Register, $tmp2$$Register, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct getAndSetS(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{
+  match(Set res (GetAndSetS mem_ptr src));
+  predicate(VM_Version::has_lqarx());
+  effect(TEMP_DEF res, TEMP cr0);
+  format %{ "GetAndSetS $res, $mem_ptr, $src" %}
+  ins_encode %{
+    __ getandseth($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  noreg, noreg, noreg, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct getAndSetS4(iRegIdst res, rarg3RegP mem_ptr, iRegIsrc src, iRegIsrc tmp1, iRegIsrc tmp2, flagsRegCR0 cr0) %{
+  match(Set res (GetAndSetS mem_ptr src));
+  predicate(!VM_Version::has_lqarx());
+  effect(TEMP_DEF res, USE_KILL mem_ptr, TEMP tmp1, TEMP tmp2, TEMP cr0);
+  format %{ "GetAndSetS $res, $mem_ptr, $src" %}
+  ins_encode %{
+    __ getandseth($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  R0, $tmp1$$Register, $tmp2$$Register, MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
   ins_pipe(pipe_class_default);
 %}
 
 instruct getAndSetI(iRegIdst res, iRegPdst mem_ptr, iRegIsrc src, flagsRegCR0 cr0) %{
   match(Set res (GetAndSetI mem_ptr src));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0);
   format %{ "GetAndSetI $res, $mem_ptr, $src" %}
-  // Variable size: instruction count smaller if regs are disjoint.
-  ins_encode( enc_GetAndSetI(res, mem_ptr, src) );
+  ins_encode %{
+    __ getandsetw($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
   ins_pipe(pipe_class_default);
 %}
 
 instruct getAndSetL(iRegLdst res, iRegPdst mem_ptr, iRegLsrc src, flagsRegCR0 cr0) %{
   match(Set res (GetAndSetL mem_ptr src));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0);
   format %{ "GetAndSetL $res, $mem_ptr, $src" %}
-  // Variable size: instruction count smaller if regs are disjoint.
-  ins_encode( enc_GetAndSetL(res, mem_ptr, src) );
+  ins_encode %{
+    __ getandsetd($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
   ins_pipe(pipe_class_default);
 %}
 
 instruct getAndSetP(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src, flagsRegCR0 cr0) %{
   match(Set res (GetAndSetP mem_ptr src));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0);
   format %{ "GetAndSetP $res, $mem_ptr, $src" %}
-  // Variable size: instruction count smaller if regs are disjoint.
-  ins_encode( enc_GetAndSetL(res, mem_ptr, src) );
+  ins_encode %{
+    __ getandsetd($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
   ins_pipe(pipe_class_default);
 %}
 
 instruct getAndSetN(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src, flagsRegCR0 cr0) %{
   match(Set res (GetAndSetN mem_ptr src));
-  effect(TEMP cr0);
+  effect(TEMP_DEF res, TEMP cr0);
   format %{ "GetAndSetN $res, $mem_ptr, $src" %}
-  // Variable size: instruction count smaller if regs are disjoint.
-  ins_encode( enc_GetAndSetI(res, mem_ptr, src) );
+  ins_encode %{
+    __ getandsetw($res$$Register, $src$$Register, $mem_ptr$$Register,
+                  MacroAssembler::cmpxchgx_hint_atomic_update());
+    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+      __ isync();
+    } else {
+      __ sync();
+    }
+  %}
   ins_pipe(pipe_class_default);
 %}
 
@@ -11360,7 +11715,7 @@
   effect(USE_KILL cnt, USE_KILL base, KILL ctr);
   ins_cost(MEMORY_REF_COST);
 
-  ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
+  ins_alignment(4); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
 
   format %{ "ClearArray $cnt, $base" %}
   ins_encode %{
@@ -11686,7 +12041,6 @@
                        flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
   match(Set result (StrIndexOfChar (Binary haystack haycnt) ch));
   effect(TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
-  predicate(CompactStrings);
   ins_cost(180);
 
   format %{ "String IndexOfChar $haystack[0..$haycnt], $ch"
@@ -11948,283 +12302,6 @@
 %}
 
 
-// String_IndexOf for needle of length 1.
-//
-// Match needle into immediate operands: no loadConP node needed. Saves one
-// register and two instructions over string_indexOf_imm1Node.
-//
-// Assumes register result differs from all input registers.
-//
-// Preserves registers haystack, haycnt
-// Kills     registers tmp1, tmp2
-// Defines   registers result
-//
-// Use dst register classes if register gets killed, as it is the case for tmp registers!
-//
-// Unfortunately this does not match too often. In many situations the AddP is used
-// by several nodes, even several StrIndexOf nodes, breaking the match tree.
-instruct string_indexOf_imm1_char(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
-                                  immP needleImm, immL offsetImm, immI_1 needlecntImm,
-                                  iRegIdst tmp1, iRegIdst tmp2,
-                                  flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
-  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, KILL ctr);
-
-  ins_cost(150);
-  format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]"
-            "-> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %}
-
-  ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted
-  ins_encode %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-    immPOper *needleOper = (immPOper *)$needleImm;
-    const TypeOopPtr *t = needleOper->type()->isa_oopptr();
-    ciTypeArray* needle_values = t->const_oop()->as_type_array();  // Pointer to live char *
-    jchar chr;
-    if (java_lang_String::has_coder_field()) {
-      // New compact strings byte array strings
-#ifdef VM_LITTLE_ENDIAN
-    chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) |
-           ((jchar)(unsigned char)needle_values->element_value(0).as_byte());
-#else
-    chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) |
-           ((jchar)(unsigned char)needle_values->element_value(1).as_byte());
-#endif
-    } else {
-      // Old char array strings
-      chr = needle_values->char_at(0);
-    }
-    __ string_indexof_1($result$$Register,
-                        $haystack$$Register, $haycnt$$Register,
-                        R0, chr,
-                        $tmp1$$Register, $tmp2$$Register);
-  %}
-  ins_pipe(pipe_class_compare);
-%}
-
-// String_IndexOf for needle of length 1.
-//
-// Special case requires less registers and emits less instructions.
-//
-// Assumes register result differs from all input registers.
-//
-// Preserves registers haystack, haycnt
-// Kills     registers tmp1, tmp2, needle
-// Defines   registers result
-//
-// Use dst register classes if register gets killed, as it is the case for tmp registers!
-instruct string_indexOf_imm1(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
-                             rscratch2RegP needle, immI_1 needlecntImm,
-                             iRegIdst tmp1, iRegIdst tmp2,
-                             flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
-  match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
-  effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result,
-         TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
-  // Required for EA: check if it is still a type_array.
-  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);
-
-  ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
-
-  format %{ "String IndexOf SCL1 $haystack[0..$haycnt], $needle[0..$needlecntImm]"
-            " -> $result \t// KILL $haycnt, $needle, $tmp1, $tmp2, $cr0, $cr1" %}
-  ins_encode %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-    Node *ndl = in(operand_index($needle));  // The node that defines needle.
-    ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array();
-    guarantee(needle_values, "sanity");
-    jchar chr;
-    if (java_lang_String::has_coder_field()) {
-      // New compact strings byte array strings
-#ifdef VM_LITTLE_ENDIAN
-    chr = (((jchar)(unsigned char)needle_values->element_value(1).as_byte()) << 8) |
-           ((jchar)(unsigned char)needle_values->element_value(0).as_byte());
-#else
-    chr = (((jchar)(unsigned char)needle_values->element_value(0).as_byte()) << 8) |
-           ((jchar)(unsigned char)needle_values->element_value(1).as_byte());
-#endif
-    } else {
-      // Old char array strings
-      chr = needle_values->char_at(0);
-    }
-    __ string_indexof_1($result$$Register,
-                        $haystack$$Register, $haycnt$$Register,
-                        R0, chr,
-                        $tmp1$$Register, $tmp2$$Register);
-  %}
-  ins_pipe(pipe_class_compare);
-%}
-
-// String_IndexOfChar
-//
-// Assumes register result differs from all input registers.
-//
-// Preserves registers haystack, haycnt
-// Kills     registers tmp1, tmp2
-// Defines   registers result
-//
-// Use dst register classes if register gets killed, as it is the case for tmp registers!
-instruct string_indexOfChar(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt,
-                            iRegIsrc ch, iRegIdst tmp1, iRegIdst tmp2,
-                            flagsRegCR0 cr0, flagsRegCR1 cr1, regCTR ctr) %{
-  match(Set result (StrIndexOfChar (Binary haystack haycnt) ch));
-  effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1, KILL ctr);
-  predicate(SpecialStringIndexOf && !CompactStrings);
-  ins_cost(180);
-
-  ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
-
-  format %{ "String IndexOfChar $haystack[0..$haycnt], $ch"
-            " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $cr0, $cr1" %}
-  ins_encode %{
-    __ string_indexof_1($result$$Register,
-                        $haystack$$Register, $haycnt$$Register,
-                        $ch$$Register, 0 /* this is not used if the character is already in a register */,
-                        $tmp1$$Register, $tmp2$$Register);
-  %}
-  ins_pipe(pipe_class_compare);
-%}
-
-// String_IndexOf.
-//
-// Length of needle as immediate. This saves instruction loading constant needle
-// length.
-// @@@ TODO Specify rules for length < 8 or so, and roll out comparison of needle
-// completely or do it in vector instruction. This should save registers for
-// needlecnt and needle.
-//
-// Assumes register result differs from all input registers.
-// Overwrites haycnt, needlecnt.
-// Use dst register classes if register gets killed, as it is the case for tmp registers!
-instruct string_indexOf_imm(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt,
-                            iRegPsrc needle, uimmI15 needlecntImm,
-                            iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5,
-                            flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
-  match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
-  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, KILL ctr);
-  // Required for EA: check if it is still a type_array.
-  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);
-
-  ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
-
-  format %{ "String IndexOf SCL $haystack[0..$haycnt], $needle[0..$needlecntImm]"
-            " -> $result \t// KILL $haycnt, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5, $cr0, $cr1" %}
-  ins_encode %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-    Node *ndl = in(operand_index($needle));  // The node that defines needle.
-    ciTypeArray* needle_values = ndl->bottom_type()->is_aryptr()->const_oop()->as_type_array();
-
-    __ string_indexof($result$$Register,
-                      $haystack$$Register, $haycnt$$Register,
-                      $needle$$Register, needle_values, $tmp5$$Register, $needlecntImm$$constant,
-                      $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register);
-  %}
-  ins_pipe(pipe_class_compare);
-%}
-
-// StrIndexOf node.
-//
-// Assumes register result differs from all input registers.
-// Overwrites haycnt, needlecnt.
-// Use dst register classes if register gets killed, as it is the case for tmp registers!
-instruct string_indexOf(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt, iRegPsrc needle, rscratch2RegI needlecnt,
-                        iRegLdst tmp1, iRegLdst tmp2, iRegLdst tmp3, iRegLdst tmp4,
-                        flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
-  match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt)));
-  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, KILL ctr);
-  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.
-
-  format %{ "String IndexOf $haystack[0..$haycnt], $needle[0..$needlecnt]"
-             " -> $result \t// KILL $haycnt, $needlecnt, $tmp1, $tmp2, $tmp3, $tmp4, $cr0, $cr1" %}
-  ins_encode %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-    __ string_indexof($result$$Register,
-                      $haystack$$Register, $haycnt$$Register,
-                      $needle$$Register, NULL, $needlecnt$$Register, 0,  // needlecnt not constant.
-                      $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register);
-  %}
-  ins_pipe(pipe_class_compare);
-%}
-
-// String equals with immediate.
-instruct string_equals_imm(iRegPsrc str1, iRegPsrc str2, uimmI15 cntImm, iRegIdst result,
-                           iRegPdst tmp1, iRegPdst tmp2,
-                           flagsRegCR0 cr0, flagsRegCR6 cr6, regCTR ctr) %{
-  match(Set result (StrEquals (Binary str1 str2) cntImm));
-  effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2,
-         KILL cr0, KILL cr6, KILL ctr);
-  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.
-
-  format %{ "String Equals SCL [0..$cntImm]($str1),[0..$cntImm]($str2)"
-            " -> $result \t// KILL $cr0, $cr6, $ctr, TEMP $result, $tmp1, $tmp2" %}
-  ins_encode %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-    __ char_arrays_equalsImm($str1$$Register, $str2$$Register, $cntImm$$constant,
-                             $result$$Register, $tmp1$$Register, $tmp2$$Register);
-  %}
-  ins_pipe(pipe_class_compare);
-%}
-
-// String equals.
-// Use dst register classes if register gets killed, as it is the case for TEMP operands!
-instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst result,
-                       iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3, iRegPdst tmp4, iRegPdst tmp5,
-                       flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
-  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 && !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.
-
-  format %{ "String Equals [0..$cnt]($str1),[0..$cnt]($str2) -> $result"
-            " \t// KILL $cr0, $cr1, $cr6, $ctr, TEMP $result, $tmp1, $tmp2, $tmp3, $tmp4, $tmp5" %}
-  ins_encode %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-    __ char_arrays_equals($str1$$Register, $str2$$Register, $cnt$$Register, $result$$Register,
-                          $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register, $tmp5$$Register);
-  %}
-  ins_pipe(pipe_class_compare);
-%}
-
-// String compare.
-// Char[] pointers are passed in.
-// 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);
-
-  ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
-
-  format %{ "String Compare $str1[0..$cnt1], $str2[0..$cnt2] -> $result"
-            " \t// TEMP $tmp, $result KILLs $str1, $cnt1, $str2, $cnt2, $cr0, $ctr" %}
-  ins_encode %{
-    // TODO: PPC port $archOpcode(ppc64Opcode_compound);
-    __ string_compare($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register,
-                      $result$$Register, $tmp$$Register);
-  %}
-  ins_pipe(pipe_class_compare);
-%}
-
 //---------- Min/Max Instructions ---------------------------------------------
 
 instruct minI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -1123,7 +1123,10 @@
     Register tmp3 = R8_ARG6;
     Register tmp4 = R9_ARG7;
 
-    Label l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8, l_9;
+    VectorSRegister tmp_vsr1  = VSR1;
+    VectorSRegister tmp_vsr2  = VSR2;
+
+    Label l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8, l_9, l_10;
 
     // Don't try anything fancy if arrays don't have many elements.
     __ li(tmp3, 0);
@@ -1178,6 +1181,8 @@
       __ andi_(R5_ARG3, R5_ARG3, 31);
       __ mtctr(tmp1);
 
+     if (!VM_Version::has_vsx()) {
+
       __ bind(l_8);
       // Use unrolled version for mass copying (copy 32 elements a time)
       // Load feeding store gets zero latency on Power6, however not on Power5.
@@ -1193,7 +1198,44 @@
       __ addi(R3_ARG1, R3_ARG1, 32);
       __ addi(R4_ARG2, R4_ARG2, 32);
       __ bdnz(l_8);
-    }
+
+    } else { // Processor supports VSX, so use it to mass copy.
+
+      // Prefetch the data into the L2 cache.
+      __ dcbt(R3_ARG1, 0);
+
+      // If supported set DSCR pre-fetch to deepest.
+      if (VM_Version::has_mfdscr()) {
+        __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+        __ mtdscr(tmp2);
+      }
+
+      __ li(tmp1, 16);
+
+      // Backbranch target aligned to 32-byte. Not 16-byte align as
+      // loop contains < 8 instructions that fit inside a single
+      // i-cache sector.
+      __ align(32);
+
+      __ bind(l_10);
+      // Use loop with VSX load/store instructions to
+      // copy 32 elements a time.
+      __ lxvd2x(tmp_vsr1, 0, R3_ARG1);     // Load src
+      __ stxvd2x(tmp_vsr1, 0, R4_ARG2);    // Store to dst
+      __ lxvd2x(tmp_vsr2, tmp1, R3_ARG1);  // Load src + 16
+      __ stxvd2x(tmp_vsr2, tmp1, R4_ARG2); // Store to dst + 16
+      __ addi(R3_ARG1, R3_ARG1, 32);       // Update src+=32
+      __ addi(R4_ARG2, R4_ARG2, 32);       // Update dsc+=32
+      __ bdnz(l_10);                       // Dec CTR and loop if not zero.
+
+      // Restore DSCR pre-fetch value.
+      if (VM_Version::has_mfdscr()) {
+        __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+        __ mtdscr(tmp2);
+      }
+
+    } // VSX
+   } // FasterArrayCopy
 
     __ bind(l_6);
 
@@ -1557,7 +1599,10 @@
     Register tmp3 = R8_ARG6;
     Register tmp4 = R0;
 
-    Label l_1, l_2, l_3, l_4, l_5, l_6;
+    VectorSRegister tmp_vsr1  = VSR1;
+    VectorSRegister tmp_vsr2  = VSR2;
+
+    Label l_1, l_2, l_3, l_4, l_5, l_6, l_7;
 
     // for short arrays, just do single element copy
     __ li(tmp3, 0);
@@ -1593,6 +1638,8 @@
       __ andi_(R5_ARG3, R5_ARG3, 7);
       __ mtctr(tmp1);
 
+     if (!VM_Version::has_vsx()) {
+
       __ bind(l_6);
       // Use unrolled version for mass copying (copy 8 elements a time).
       // Load feeding store gets zero latency on power6, however not on power 5.
@@ -1608,7 +1655,44 @@
       __ addi(R3_ARG1, R3_ARG1, 32);
       __ addi(R4_ARG2, R4_ARG2, 32);
       __ bdnz(l_6);
-    }
+
+    } else { // Processor supports VSX, so use it to mass copy.
+
+      // Prefetch the data into the L2 cache.
+      __ dcbt(R3_ARG1, 0);
+
+      // If supported set DSCR pre-fetch to deepest.
+      if (VM_Version::has_mfdscr()) {
+        __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+        __ mtdscr(tmp2);
+      }
+
+      __ li(tmp1, 16);
+
+      // Backbranch target aligned to 32-byte. Not 16-byte align as
+      // loop contains < 8 instructions that fit inside a single
+      // i-cache sector.
+      __ align(32);
+
+      __ bind(l_7);
+      // Use loop with VSX load/store instructions to
+      // copy 8 elements a time.
+      __ lxvd2x(tmp_vsr1, 0, R3_ARG1);     // Load src
+      __ stxvd2x(tmp_vsr1, 0, R4_ARG2);    // Store to dst
+      __ lxvd2x(tmp_vsr2, tmp1, R3_ARG1);  // Load src + 16
+      __ stxvd2x(tmp_vsr2, tmp1, R4_ARG2); // Store to dst + 16
+      __ addi(R3_ARG1, R3_ARG1, 32);       // Update src+=32
+      __ addi(R4_ARG2, R4_ARG2, 32);       // Update dsc+=32
+      __ bdnz(l_7);                        // Dec CTR and loop if not zero.
+
+      // Restore DSCR pre-fetch value.
+      if (VM_Version::has_mfdscr()) {
+        __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+        __ mtdscr(tmp2);
+      }
+
+    } // VSX
+   } // FasterArrayCopy
 
     // copy 1 element at a time
     __ bind(l_2);
@@ -1757,7 +1841,10 @@
     Register tmp3 = R8_ARG6;
     Register tmp4 = R0;
 
-    Label l_1, l_2, l_3, l_4;
+    Label l_1, l_2, l_3, l_4, l_5;
+
+    VectorSRegister tmp_vsr1  = VSR1;
+    VectorSRegister tmp_vsr2  = VSR2;
 
     { // FasterArrayCopy
       __ cmpwi(CCR0, R5_ARG3, 3);
@@ -1767,6 +1854,7 @@
       __ andi_(R5_ARG3, R5_ARG3, 3);
       __ mtctr(tmp1);
 
+    if (!VM_Version::has_vsx()) {
       __ bind(l_4);
       // Use unrolled version for mass copying (copy 4 elements a time).
       // Load feeding store gets zero latency on Power6, however not on Power5.
@@ -1782,7 +1870,44 @@
       __ addi(R3_ARG1, R3_ARG1, 32);
       __ addi(R4_ARG2, R4_ARG2, 32);
       __ bdnz(l_4);
-    }
+
+    } else { // Processor supports VSX, so use it to mass copy.
+
+      // Prefetch the data into the L2 cache.
+      __ dcbt(R3_ARG1, 0);
+
+      // If supported set DSCR pre-fetch to deepest.
+      if (VM_Version::has_mfdscr()) {
+        __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+        __ mtdscr(tmp2);
+      }
+
+      __ li(tmp1, 16);
+
+      // Backbranch target aligned to 32-byte. Not 16-byte align as
+      // loop contains < 8 instructions that fit inside a single
+      // i-cache sector.
+      __ align(32);
+
+      __ bind(l_5);
+      // Use loop with VSX load/store instructions to
+      // copy 4 elements a time.
+      __ lxvd2x(tmp_vsr1, 0, R3_ARG1);     // Load src
+      __ stxvd2x(tmp_vsr1, 0, R4_ARG2);    // Store to dst
+      __ lxvd2x(tmp_vsr2, tmp1, R3_ARG1);  // Load src + 16
+      __ stxvd2x(tmp_vsr2, tmp1, R4_ARG2); // Store to dst + 16
+      __ addi(R3_ARG1, R3_ARG1, 32);       // Update src+=32
+      __ addi(R4_ARG2, R4_ARG2, 32);       // Update dsc+=32
+      __ bdnz(l_5);                        // Dec CTR and loop if not zero.
+
+      // Restore DSCR pre-fetch value.
+      if (VM_Version::has_mfdscr()) {
+        __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+        __ mtdscr(tmp2);
+      }
+
+    } // VSX
+   } // FasterArrayCopy
 
     // copy 1 element at a time
     __ bind(l_3);
--- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -845,9 +845,40 @@
   __ b(continue_entry);
 }
 
+// See if we've got enough room on the stack for locals plus overhead below
+// JavaThread::stack_overflow_limit(). If not, throw a StackOverflowError
+// without going through the signal handler, i.e., reserved and yellow zones
+// will not be made usable. The shadow zone must suffice to handle the
+// overflow.
+//
+// Kills Rmem_frame_size, Rscratch1.
 void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rmem_frame_size, Register Rscratch1) {
+  Label done;
   assert_different_registers(Rmem_frame_size, Rscratch1);
-  __ generate_stack_overflow_check_with_compare_and_throw(Rmem_frame_size, Rscratch1);
+
+  BLOCK_COMMENT("stack_overflow_check_with_compare {");
+  __ sub(Rmem_frame_size, R1_SP, Rmem_frame_size);
+  __ ld(Rscratch1, thread_(stack_overflow_limit));
+  __ cmpld(CCR0/*is_stack_overflow*/, Rmem_frame_size, Rscratch1);
+  __ bgt(CCR0/*is_stack_overflow*/, done);
+
+  // The stack overflows. Load target address of the runtime stub and call it.
+  assert(StubRoutines::throw_StackOverflowError_entry() != NULL, "generated in wrong order");
+  __ load_const_optimized(Rscratch1, (StubRoutines::throw_StackOverflowError_entry()), R0);
+  __ mtctr(Rscratch1);
+  // Restore caller_sp.
+#ifdef ASSERT
+  __ ld(Rscratch1, 0, R1_SP);
+  __ ld(R0, 0, R21_sender_SP);
+  __ cmpd(CCR0, R0, Rscratch1);
+  __ asm_assert_eq("backlink", 0x547);
+#endif // ASSERT
+  __ mr(R1_SP, R21_sender_SP);
+  __ bctr();
+
+  __ align(32, 12);
+  __ bind(done);
+  BLOCK_COMMENT("} stack_overflow_check_with_compare");
 }
 
 void TemplateInterpreterGenerator::unlock_method(bool check_exceptions) {
@@ -1014,10 +1045,10 @@
   // Enlarge by locals-parameters (not in case of native_call), shrink by ESP-SP-ABI48.
 
   if (!native_call) {
-    // --------------------------------------------------------------------------
-    // Stack overflow check
-
-    Label cont;
+    // Stack overflow check.
+    // Native calls don't need the stack size check since they have no
+    // expression stack and the arguments are already on the stack and
+    // we only add a handful of words to the stack.
     __ add(R11_scratch1, parent_frame_resize, top_frame_size);
     generate_stack_overflow_check(R11_scratch1, R12_scratch2);
   }
--- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2013, 2016 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -4093,20 +4093,8 @@
   __ lock_object(Rcurrent_monitor, Robj_to_lock);
 
   // Check if there's enough space on the stack for the monitors after locking.
-  Label Lskip_stack_check;
-  // Optimization: If the monitors stack section is less then a std page size (4K) don't run
-  // the stack check. There should be enough shadow pages to fit that in.
-  __ ld(Rscratch3, 0, R1_SP);
-  __ sub(Rscratch3, Rscratch3, R26_monitor);
-  __ cmpdi(CCR0, Rscratch3, 4*K);
-  __ blt(CCR0, Lskip_stack_check);
-
-  DEBUG_ONLY(__ untested("stack overflow check during monitor enter");)
-  __ li(Rscratch1, 0);
-  __ generate_stack_overflow_check_with_compare_and_throw(Rscratch1, Rscratch2);
-
-  __ align(32, 12);
-  __ bind(Lskip_stack_check);
+  // This emits a single store.
+  __ generate_stack_overflow_check(0);
 
   // The bcp has already been incremented. Just need to dispatch to next instruction.
   __ dispatch_next(vtos);
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp	Fri Jul 01 16:50:34 2016 -0700
@@ -59,11 +59,11 @@
 // Stack slots are 2X larger in LP64 than in the 32 bit VM.
 define_pd_global(intx, ThreadStackSize,       1024);
 define_pd_global(intx, VMThreadStackSize,     1024);
-#define DEFAULT_STACK_SHADOW_PAGES (10 DEBUG_ONLY(+1))
+#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+2))
 #else
 define_pd_global(intx, ThreadStackSize,       512);
 define_pd_global(intx, VMThreadStackSize,     512);
-#define DEFAULT_STACK_SHADOW_PAGES (3 DEBUG_ONLY(+1))
+#define DEFAULT_STACK_SHADOW_PAGES (6 DEBUG_ONLY(+2))
 #endif // _LP64
 
 #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
--- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -578,51 +578,39 @@
   __ lock_object(Lmonitors, O0);
 }
 
-
+// See if we've got enough room on the stack for locals plus overhead below
+// JavaThread::stack_overflow_limit(). If not, throw a StackOverflowError
+// without going through the signal handler, i.e., reserved and yellow zones
+// will not be made usable. The shadow zone must suffice to handle the
+// overflow.
 void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe_size,
-                                                         Register Rscratch,
-                                                         Register Rscratch2) {
+                                                                 Register Rscratch) {
   const int page_size = os::vm_page_size();
   Label after_frame_check;
 
-  assert_different_registers(Rframe_size, Rscratch, Rscratch2);
+  assert_different_registers(Rframe_size, Rscratch);
 
   __ set(page_size, Rscratch);
   __ cmp_and_br_short(Rframe_size, Rscratch, Assembler::lessEqual, Assembler::pt, after_frame_check);
 
-  // get the stack base, and in debug, verify it is non-zero
-  __ ld_ptr( G2_thread, Thread::stack_base_offset(), Rscratch );
+  // Get the stack overflow limit, and in debug, verify it is non-zero.
+  __ ld_ptr(G2_thread, JavaThread::stack_overflow_limit_offset(), Rscratch);
 #ifdef ASSERT
-  Label base_not_zero;
-  __ br_notnull_short(Rscratch, Assembler::pn, base_not_zero);
-  __ stop("stack base is zero in generate_stack_overflow_check");
-  __ bind(base_not_zero);
+  Label limit_ok;
+  __ br_notnull_short(Rscratch, Assembler::pn, limit_ok);
+  __ stop("stack overflow limit is zero in generate_stack_overflow_check");
+  __ bind(limit_ok);
 #endif
 
-  // get the stack size, and in debug, verify it is non-zero
-  assert( sizeof(size_t) == sizeof(intptr_t), "wrong load size" );
-  __ ld_ptr( G2_thread, Thread::stack_size_offset(), Rscratch2 );
-#ifdef ASSERT
-  Label size_not_zero;
-  __ br_notnull_short(Rscratch2, Assembler::pn, size_not_zero);
-  __ stop("stack size is zero in generate_stack_overflow_check");
-  __ bind(size_not_zero);
-#endif
+  // Add in the size of the frame (which is the same as subtracting it from the
+  // SP, which would take another register.
+  __ add(Rscratch, Rframe_size, Rscratch);
 
-  // compute the beginning of the protected zone minus the requested frame size
-  __ sub( Rscratch, Rscratch2,   Rscratch );
-  __ set(MAX2(JavaThread::stack_shadow_zone_size(), JavaThread::stack_guard_zone_size()), Rscratch2 );
-  __ add( Rscratch, Rscratch2,   Rscratch );
-
-  // Add in the size of the frame (which is the same as subtracting it from the
-  // SP, which would take another register
-  __ add( Rscratch, Rframe_size, Rscratch );
-
-  // the frame is greater than one page in size, so check against
-  // the bottom of the stack
+  // The frame is greater than one page in size, so check against
+  // the bottom of the stack.
   __ cmp_and_brx_short(SP, Rscratch, Assembler::greaterUnsigned, Assembler::pt, after_frame_check);
 
-  // the stack will overflow, throw an exception
+  // The stack will overflow, throw an exception.
 
   // Note that SP is restored to sender's sp (in the delay slot). This
   // is necessary if the sender's frame is an extended compiled frame
@@ -636,8 +624,8 @@
   __ jump_to(stub, Rscratch);
   __ delayed()->mov(O5_savedSP, SP);
 
-  // if you get to here, then there is enough stack space
-  __ bind( after_frame_check );
+  // If you get to here, then there is enough stack space.
+  __ bind(after_frame_check);
 }
 
 
@@ -821,40 +809,44 @@
     __ add( Gframe_size,  extra_space, Gframe_size);
     __ round_to( Gframe_size, WordsPerLong );
     __ sll( Gframe_size, LogBytesPerWord, Gframe_size );
+
+    // Native calls don't need the stack size check since they have no
+    // expression stack and the arguments are already on the stack and
+    // we only add a handful of words to the stack.
   } else {
 
     //
     // Compute number of locals in method apart from incoming parameters
     //
-    const Address size_of_locals    (Otmp1, ConstMethod::size_of_locals_offset());
-    __ ld_ptr( constMethod, Otmp1 );
-    __ lduh( size_of_locals, Otmp1 );
-    __ sub( Otmp1, Glocals_size, Glocals_size );
-    __ round_to( Glocals_size, WordsPerLong );
-    __ sll( Glocals_size, Interpreter::logStackElementSize, Glocals_size );
+    const Address size_of_locals(Otmp1, ConstMethod::size_of_locals_offset());
+    __ ld_ptr(constMethod, Otmp1);
+    __ lduh(size_of_locals, Otmp1);
+    __ sub(Otmp1, Glocals_size, Glocals_size);
+    __ round_to(Glocals_size, WordsPerLong);
+    __ sll(Glocals_size, Interpreter::logStackElementSize, Glocals_size);
 
-    // see if the frame is greater than one page in size. If so,
-    // then we need to verify there is enough stack space remaining
+    // See if the frame is greater than one page in size. If so,
+    // then we need to verify there is enough stack space remaining.
     // Frame_size = (max_stack + extra_space) * BytesPerWord;
-    __ ld_ptr( constMethod, Gframe_size );
-    __ lduh( Gframe_size, in_bytes(ConstMethod::max_stack_offset()), Gframe_size );
-    __ add( Gframe_size, extra_space, Gframe_size );
-    __ round_to( Gframe_size, WordsPerLong );
-    __ sll( Gframe_size, Interpreter::logStackElementSize, Gframe_size);
+    __ ld_ptr(constMethod, Gframe_size);
+    __ lduh(Gframe_size, in_bytes(ConstMethod::max_stack_offset()), Gframe_size);
+    __ add(Gframe_size, extra_space, Gframe_size);
+    __ round_to(Gframe_size, WordsPerLong);
+    __ sll(Gframe_size, Interpreter::logStackElementSize, Gframe_size);
 
     // Add in java locals size for stack overflow check only
-    __ add( Gframe_size, Glocals_size, Gframe_size );
+    __ add(Gframe_size, Glocals_size, Gframe_size);
 
     const Register Otmp2 = O4;
     assert_different_registers(Otmp1, Otmp2, O5_savedSP);
-    generate_stack_overflow_check(Gframe_size, Otmp1, Otmp2);
+    generate_stack_overflow_check(Gframe_size, Otmp1);
 
-    __ sub( Gframe_size, Glocals_size, Gframe_size);
+    __ sub(Gframe_size, Glocals_size, Gframe_size);
 
     //
     // bump SP to accomodate the extra locals
     //
-    __ sub( SP, Glocals_size, SP );
+    __ sub(SP, Glocals_size, SP);
   }
 
   //
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -1173,6 +1173,23 @@
   emit_arith_operand(0x81, rax, dst, imm32);
 }
 
+void Assembler::addb(Address dst, int imm8) {
+  InstructionMark im(this);
+  prefix(dst);
+  emit_int8((unsigned char)0x80);
+  emit_operand(rax, dst, 1);
+  emit_int8(imm8);
+}
+
+void Assembler::addw(Address dst, int imm16) {
+  InstructionMark im(this);
+  emit_int8(0x66);
+  prefix(dst);
+  emit_int8((unsigned char)0x81);
+  emit_operand(rax, dst, 2);
+  emit_int16(imm16);
+}
+
 void Assembler::addl(Address dst, Register src) {
   InstructionMark im(this);
   prefix(dst, src);
@@ -4567,6 +4584,23 @@
   emit_int8((unsigned char)(imm8 & 0xFF));
 }
 
+void Assembler::xaddb(Address dst, Register src) {
+  InstructionMark im(this);
+  prefix(dst, src, true);
+  emit_int8(0x0F);
+  emit_int8((unsigned char)0xC0);
+  emit_operand(src, dst);
+}
+
+void Assembler::xaddw(Address dst, Register src) {
+  InstructionMark im(this);
+  emit_int8(0x66);
+  prefix(dst, src);
+  emit_int8(0x0F);
+  emit_int8((unsigned char)0xC1);
+  emit_operand(src, dst);
+}
+
 void Assembler::xaddl(Address dst, Register src) {
   InstructionMark im(this);
   prefix(dst, src);
@@ -4593,6 +4627,21 @@
   }
 }
 
+void Assembler::xchgb(Register dst, Address src) { // xchg
+  InstructionMark im(this);
+  prefix(src, dst, true);
+  emit_int8((unsigned char)0x86);
+  emit_operand(dst, src);
+}
+
+void Assembler::xchgw(Register dst, Address src) { // xchg
+  InstructionMark im(this);
+  emit_int8(0x66);
+  prefix(src, dst);
+  emit_int8((unsigned char)0x87);
+  emit_operand(dst, src);
+}
+
 void Assembler::xchgl(Register dst, Address src) { // xchg
   InstructionMark im(this);
   prefix(src, dst);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Fri Jul 01 16:50:34 2016 -0700
@@ -881,6 +881,9 @@
   void adcq(Register dst, Address src);
   void adcq(Register dst, Register src);
 
+  void addb(Address dst, int imm8);
+  void addw(Address dst, int imm16);
+
   void addl(Address dst, int32_t imm32);
   void addl(Address dst, Register src);
   void addl(Register dst, int32_t imm32);
@@ -1816,12 +1819,15 @@
 
   void xabort(int8_t imm8);
 
+  void xaddb(Address dst, Register src);
+  void xaddw(Address dst, Register src);
   void xaddl(Address dst, Register src);
-
   void xaddq(Address dst, Register src);
 
   void xbegin(Label& abort, relocInfo::relocType rtype = relocInfo::none);
 
+  void xchgb(Register reg, Address adr);
+  void xchgw(Register reg, Address adr);
   void xchgl(Register reg, Address adr);
   void xchgl(Register dst, Register src);
 
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp	Fri Jul 01 16:50:34 2016 -0700
@@ -473,7 +473,11 @@
   __ jmp(do_continue, relocInfo::none);
 }
 
-// See if we've got enough room on the stack for locals plus overhead.
+// See if we've got enough room on the stack for locals plus overhead below
+// JavaThread::stack_overflow_limit(). If not, throw a StackOverflowError
+// without going through the signal handler, i.e., reserved and yellow zones
+// will not be made usable. The shadow zone must suffice to handle the
+// overflow.
 // The expression stack grows down incrementally, so the normal guard
 // page mechanism will work for that.
 //
@@ -518,40 +522,26 @@
   __ get_thread(thread);
 #endif
 
-  const Address stack_base(thread, Thread::stack_base_offset());
-  const Address stack_size(thread, Thread::stack_size_offset());
+  const Address stack_limit(thread, JavaThread::stack_overflow_limit_offset());
 
   // locals + overhead, in bytes
   __ mov(rax, rdx);
-  __ shlptr(rax, Interpreter::logStackElementSize);  // 2 slots per parameter.
+  __ shlptr(rax, Interpreter::logStackElementSize); // Convert parameter count to bytes.
   __ addptr(rax, overhead_size);
 
 #ifdef ASSERT
-  Label stack_base_okay, stack_size_okay;
-  // verify that thread stack base is non-zero
-  __ cmpptr(stack_base, (int32_t)NULL_WORD);
-  __ jcc(Assembler::notEqual, stack_base_okay);
-  __ stop("stack base is zero");
-  __ bind(stack_base_okay);
-  // verify that thread stack size is non-zero
-  __ cmpptr(stack_size, 0);
-  __ jcc(Assembler::notEqual, stack_size_okay);
-  __ stop("stack size is zero");
-  __ bind(stack_size_okay);
+  Label limit_okay;
+  // Verify that thread stack overflow limit is non-zero.
+  __ cmpptr(stack_limit, (int32_t)NULL_WORD);
+  __ jcc(Assembler::notEqual, limit_okay);
+  __ stop("stack overflow limit is zero");
+  __ bind(limit_okay);
 #endif
 
-  // Add stack base to locals and subtract stack size
-  __ addptr(rax, stack_base);
-  __ subptr(rax, stack_size);
+  // Add locals/frame size to stack limit.
+  __ addptr(rax, stack_limit);
 
-  // Use the bigger size for banging.
-  const int max_bang_size = (int)MAX2(JavaThread::stack_shadow_zone_size(),
-                                      JavaThread::stack_guard_zone_size());
-
-  // add in the red and yellow zone sizes
-  __ addptr(rax, max_bang_size);
-
-  // check against the current stack bottom
+  // Check against the current stack bottom.
   __ cmpptr(rsp, rax);
 
   __ jcc(Assembler::above, after_frame_check_pop);
@@ -782,8 +772,6 @@
   return NULL;
 }
 
-// TODO: rather than touching all pages, check against stack_overflow_limit and bang yellow page to
-// generate exception.  Windows might need this to map the shadow pages though.
 void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
   // Quick & dirty stack overflow checking: bang the stack & handle trap.
   // Note that we do the banging after the frame is setup, since the exception
@@ -945,7 +933,7 @@
   __ load_unsigned_short(t, Address(t, ConstMethod::size_of_parameters_offset()));
 
 #ifndef _LP64
-  __ shlptr(t, Interpreter::logStackElementSize);
+  __ shlptr(t, Interpreter::logStackElementSize); // Convert parameter count to bytes.
   __ addptr(t, 2*wordSize);     // allocate two more slots for JNIEnv and possible mirror
   __ subptr(rsp, t);
   __ andptr(rsp, -(StackAlignmentInBytes)); // gcc needs 16 byte aligned stacks to do XMM intrinsics
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Fri Jul 01 16:50:34 2016 -0700
@@ -2127,6 +2127,31 @@
     emit_rm( cbuf, 0x0, 1, $mem_ptr$$reg );
   %}
 
+  enc_class enc_cmpxchgb(eSIRegP mem_ptr) %{
+    // [Lock]
+    if( os::is_MP() )
+      emit_opcode(cbuf,0xF0);
+
+    // CMPXCHGB [Eptr]
+    emit_opcode(cbuf,0x0F);
+    emit_opcode(cbuf,0xB0);
+    emit_rm( cbuf, 0x0, 1, $mem_ptr$$reg );
+  %}
+
+  enc_class enc_cmpxchgw(eSIRegP mem_ptr) %{
+    // [Lock]
+    if( os::is_MP() )
+      emit_opcode(cbuf,0xF0);
+
+    // 16-bit mode
+    emit_opcode(cbuf, 0x66);
+
+    // CMPXCHGW [Eptr]
+    emit_opcode(cbuf,0x0F);
+    emit_opcode(cbuf,0xB1);
+    emit_rm( cbuf, 0x0, 1, $mem_ptr$$reg );
+  %}
+
   enc_class enc_flags_ne_to_boolean( iRegI res ) %{
     int res_encoding = $res$$reg;
 
@@ -7262,6 +7287,34 @@
   ins_pipe( pipe_cmpxchg );
 %}
 
+instruct compareAndSwapB( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr ) %{
+  match(Set res (CompareAndSwapB mem_ptr (Binary oldval newval)));
+  match(Set res (WeakCompareAndSwapB mem_ptr (Binary oldval newval)));
+  effect(KILL cr, KILL oldval);
+  format %{ "CMPXCHGB [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
+            "MOV    $res,0\n\t"
+            "JNE,s  fail\n\t"
+            "MOV    $res,1\n"
+          "fail:" %}
+  ins_encode( enc_cmpxchgb(mem_ptr),
+              enc_flags_ne_to_boolean(res) );
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndSwapS( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr ) %{
+  match(Set res (CompareAndSwapS mem_ptr (Binary oldval newval)));
+  match(Set res (WeakCompareAndSwapS mem_ptr (Binary oldval newval)));
+  effect(KILL cr, KILL oldval);
+  format %{ "CMPXCHGW [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t"
+            "MOV    $res,0\n\t"
+            "JNE,s  fail\n\t"
+            "MOV    $res,1\n"
+          "fail:" %}
+  ins_encode( enc_cmpxchgw(mem_ptr),
+              enc_flags_ne_to_boolean(res) );
+  ins_pipe( pipe_cmpxchg );
+%}
+
 instruct compareAndSwapI( rRegI res, pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
   match(Set res (CompareAndSwapI mem_ptr (Binary oldval newval)));
   match(Set res (WeakCompareAndSwapI mem_ptr (Binary oldval newval)));
@@ -7292,6 +7345,22 @@
   ins_pipe( pipe_cmpxchg );
 %}
 
+instruct compareAndExchangeB( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
+  match(Set oldval (CompareAndExchangeB mem_ptr (Binary oldval newval)));
+  effect(KILL cr);
+  format %{ "CMPXCHGB [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
+  ins_encode( enc_cmpxchgb(mem_ptr) );
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeS( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
+  match(Set oldval (CompareAndExchangeS mem_ptr (Binary oldval newval)));
+  effect(KILL cr);
+  format %{ "CMPXCHGW [$mem_ptr],$newval\t# If EAX==[$mem_ptr] Then store $newval into [$mem_ptr]\n\t" %}
+  ins_encode( enc_cmpxchgw(mem_ptr) );
+  ins_pipe( pipe_cmpxchg );
+%}
+
 instruct compareAndExchangeI( pRegP mem_ptr, eAXRegI oldval, eCXRegI newval, eFlagsReg cr) %{
   match(Set oldval (CompareAndExchangeI mem_ptr (Binary oldval newval)));
   effect(KILL cr);
@@ -7300,6 +7369,53 @@
   ins_pipe( pipe_cmpxchg );
 %}
 
+instruct xaddB_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
+  predicate(n->as_LoadStore()->result_not_used());
+  match(Set dummy (GetAndAddB mem add));
+  effect(KILL cr);
+  format %{ "ADDB  [$mem],$add" %}
+  ins_encode %{
+    if (os::is_MP()) { __ lock(); }
+    __ addb($mem$$Address, $add$$constant);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
+// Important to match to xRegI: only 8-bit regs.
+instruct xaddB( memory mem, xRegI newval, eFlagsReg cr) %{
+  match(Set newval (GetAndAddB mem newval));
+  effect(KILL cr);
+  format %{ "XADDB  [$mem],$newval" %}
+  ins_encode %{
+    if (os::is_MP()) { __ lock(); }
+    __ xaddb($mem$$Address, $newval$$Register);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct xaddS_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
+  predicate(n->as_LoadStore()->result_not_used());
+  match(Set dummy (GetAndAddS mem add));
+  effect(KILL cr);
+  format %{ "ADDS  [$mem],$add" %}
+  ins_encode %{
+    if (os::is_MP()) { __ lock(); }
+    __ addw($mem$$Address, $add$$constant);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct xaddS( memory mem, rRegI newval, eFlagsReg cr) %{
+  match(Set newval (GetAndAddS mem newval));
+  effect(KILL cr);
+  format %{ "XADDS  [$mem],$newval" %}
+  ins_encode %{
+    if (os::is_MP()) { __ lock(); }
+    __ xaddw($mem$$Address, $newval$$Register);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
 instruct xaddI_no_res( memory mem, Universe dummy, immI add, eFlagsReg cr) %{
   predicate(n->as_LoadStore()->result_not_used());
   match(Set dummy (GetAndAddI mem add));
@@ -7323,6 +7439,25 @@
   ins_pipe( pipe_cmpxchg );
 %}
 
+// Important to match to xRegI: only 8-bit regs.
+instruct xchgB( memory mem, xRegI newval) %{
+  match(Set newval (GetAndSetB mem newval));
+  format %{ "XCHGB  $newval,[$mem]" %}
+  ins_encode %{
+    __ xchgb($newval$$Register, $mem$$Address);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct xchgS( memory mem, rRegI newval) %{
+  match(Set newval (GetAndSetS mem newval));
+  format %{ "XCHGW  $newval,[$mem]" %}
+  ins_encode %{
+    __ xchgw($newval$$Register, $mem$$Address);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
 instruct xchgI( memory mem, rRegI newval) %{
   match(Set newval (GetAndSetI mem newval));
   format %{ "XCHGL  $newval,[$mem]" %}
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Fri Jul 01 16:50:34 2016 -0700
@@ -7340,6 +7340,54 @@
   ins_pipe( pipe_cmpxchg );
 %}
 
+instruct compareAndSwapB(rRegI res,
+                         memory mem_ptr,
+                         rax_RegI oldval, rRegI newval,
+                         rFlagsReg cr)
+%{
+  match(Set res (CompareAndSwapB mem_ptr (Binary oldval newval)));
+  match(Set res (WeakCompareAndSwapB mem_ptr (Binary oldval newval)));
+  effect(KILL cr, KILL oldval);
+
+  format %{ "cmpxchgb $mem_ptr,$newval\t# "
+            "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
+            "sete    $res\n\t"
+            "movzbl  $res, $res" %}
+  opcode(0x0F, 0xB0);
+  ins_encode(lock_prefix,
+             REX_reg_mem(newval, mem_ptr),
+             OpcP, OpcS,
+             reg_mem(newval, mem_ptr),
+             REX_breg(res), Opcode(0x0F), Opcode(0x94), reg(res), // sete
+             REX_reg_breg(res, res), // movzbl
+             Opcode(0xF), Opcode(0xB6), reg_reg(res, res));
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndSwapS(rRegI res,
+                         memory mem_ptr,
+                         rax_RegI oldval, rRegI newval,
+                         rFlagsReg cr)
+%{
+  match(Set res (CompareAndSwapS mem_ptr (Binary oldval newval)));
+  match(Set res (WeakCompareAndSwapS mem_ptr (Binary oldval newval)));
+  effect(KILL cr, KILL oldval);
+
+  format %{ "cmpxchgw $mem_ptr,$newval\t# "
+            "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"
+            "sete    $res\n\t"
+            "movzbl  $res, $res" %}
+  opcode(0x0F, 0xB1);
+  ins_encode(lock_prefix,
+             SizePrefix,
+             REX_reg_mem(newval, mem_ptr),          
+             OpcP, OpcS,
+             reg_mem(newval, mem_ptr),
+             REX_breg(res), Opcode(0x0F), Opcode(0x94), reg(res), // sete
+             REX_reg_breg(res, res), // movzbl
+             Opcode(0xF), Opcode(0xB6), reg_reg(res, res));
+  ins_pipe( pipe_cmpxchg );
+%}
 
 instruct compareAndSwapN(rRegI res,
                           memory mem_ptr,
@@ -7364,6 +7412,45 @@
   ins_pipe( pipe_cmpxchg );
 %}
 
+instruct compareAndExchangeB(
+                         memory mem_ptr,
+                         rax_RegI oldval, rRegI newval,
+                         rFlagsReg cr)
+%{
+  match(Set oldval (CompareAndExchangeB mem_ptr (Binary oldval newval)));
+  effect(KILL cr);
+
+  format %{ "cmpxchgb $mem_ptr,$newval\t# "
+            "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"  %}
+  opcode(0x0F, 0xB0);
+  ins_encode(lock_prefix,
+             REX_reg_mem(newval, mem_ptr),
+             OpcP, OpcS,
+             reg_mem(newval, mem_ptr) // lock cmpxchg
+             );
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct compareAndExchangeS(
+                         memory mem_ptr,
+                         rax_RegI oldval, rRegI newval,
+                         rFlagsReg cr)
+%{
+  match(Set oldval (CompareAndExchangeS mem_ptr (Binary oldval newval)));
+  effect(KILL cr);
+
+  format %{ "cmpxchgw $mem_ptr,$newval\t# "
+            "If rax == $mem_ptr then store $newval into $mem_ptr\n\t"  %}
+  opcode(0x0F, 0xB1);
+  ins_encode(lock_prefix,
+             SizePrefix,
+             REX_reg_mem(newval, mem_ptr),
+             OpcP, OpcS,
+             reg_mem(newval, mem_ptr) // lock cmpxchg
+             );
+  ins_pipe( pipe_cmpxchg );
+%}
+
 instruct compareAndExchangeI(
                          memory mem_ptr,
                          rax_RegI oldval, rRegI newval,
@@ -7441,6 +7528,52 @@
   ins_pipe( pipe_cmpxchg );
 %}
 
+instruct xaddB_no_res( memory mem, Universe dummy, immI add, rFlagsReg cr) %{
+  predicate(n->as_LoadStore()->result_not_used());
+  match(Set dummy (GetAndAddB mem add));
+  effect(KILL cr);
+  format %{ "ADDB  [$mem],$add" %}
+  ins_encode %{
+    if (os::is_MP()) { __ lock(); }
+    __ addb($mem$$Address, $add$$constant);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct xaddB( memory mem, rRegI newval, rFlagsReg cr) %{
+  match(Set newval (GetAndAddB mem newval));
+  effect(KILL cr);
+  format %{ "XADDB  [$mem],$newval" %}
+  ins_encode %{
+    if (os::is_MP()) { __ lock(); }
+    __ xaddb($mem$$Address, $newval$$Register);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct xaddS_no_res( memory mem, Universe dummy, immI add, rFlagsReg cr) %{
+  predicate(n->as_LoadStore()->result_not_used());
+  match(Set dummy (GetAndAddS mem add));
+  effect(KILL cr);
+  format %{ "ADDW  [$mem],$add" %}
+  ins_encode %{
+    if (os::is_MP()) { __ lock(); }
+    __ addw($mem$$Address, $add$$constant);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct xaddS( memory mem, rRegI newval, rFlagsReg cr) %{
+  match(Set newval (GetAndAddS mem newval));
+  effect(KILL cr);
+  format %{ "XADDW  [$mem],$newval" %}
+  ins_encode %{
+    if (os::is_MP()) { __ lock(); }
+    __ xaddw($mem$$Address, $newval$$Register);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
 instruct xaddI_no_res( memory mem, Universe dummy, immI add, rFlagsReg cr) %{
   predicate(n->as_LoadStore()->result_not_used());
   match(Set dummy (GetAndAddI mem add));
@@ -7487,6 +7620,24 @@
   ins_pipe( pipe_cmpxchg );
 %}
 
+instruct xchgB( memory mem, rRegI newval) %{
+  match(Set newval (GetAndSetB mem newval));
+  format %{ "XCHGB  $newval,[$mem]" %}
+  ins_encode %{
+    __ xchgb($newval$$Register, $mem$$Address);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
+instruct xchgS( memory mem, rRegI newval) %{
+  match(Set newval (GetAndSetS mem newval));
+  format %{ "XCHGW  $newval,[$mem]" %}
+  ins_encode %{
+    __ xchgw($newval$$Register, $mem$$Address);
+  %}
+  ins_pipe( pipe_cmpxchg );
+%}
+
 instruct xchgI( memory mem, rRegI newval) %{
   match(Set newval (GetAndSetI mem newval));
   format %{ "XCHGL  $newval,[$mem]" %}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java	Fri Jul 01 16:50:34 2016 -0700
@@ -28,6 +28,7 @@
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.PlatformKind;
 
@@ -84,13 +85,13 @@
     public static final Register lr = r30;
 
     // @formatter:off
-    public static final Register[] cpuRegisters = {
+    public static final RegisterArray cpuRegisters = new RegisterArray(
         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,
         zr,  sp
-    };
+    );
     // @formatter:on
 
     public static final RegisterCategory SIMD = new RegisterCategory("SIMD");
@@ -130,16 +131,16 @@
     public static final Register v31 = new Register(65, 31, "v31", SIMD);
 
     // @formatter:off
-    public static final Register[] simdRegisters = {
+    public static final RegisterArray simdRegisters = new RegisterArray(
         v0,  v1,  v2,  v3,  v4,  v5,  v6,  v7,
         v8,  v9,  v10, v11, v12, v13, v14, v15,
         v16, v17, v18, v19, v20, v21, v22, v23,
         v24, v25, v26, v27, v28, v29, v30, v31
-    };
+    );
     // @formatter:on
 
     // @formatter:off
-    public static final Register[] allRegisters = {
+    public static final RegisterArray allRegisters = new RegisterArray(
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
         r8,  r9,  r10, r11, r12, r13, r14, r15,
         r16, r17, r18, r19, r20, r21, r22, r23,
@@ -150,7 +151,7 @@
         v8,  v9,  v10, v11, v12, v13, v14, v15,
         v16, v17, v18, v19, v20, v21, v22, v23,
         v24, v25, v26, v27, v28, v29, v30, v31
-    };
+    );
     // @formatter:on
 
     /**
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Fri Jul 01 16:50:34 2016 -0700
@@ -33,6 +33,7 @@
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.PlatformKind;
 
@@ -131,14 +132,14 @@
     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 = {
+    public static final RegisterArray valueRegistersSSE = new RegisterArray(
         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 = {
+    public static final RegisterArray valueRegistersAVX512 = new RegisterArray(
         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
@@ -146,14 +147,14 @@
         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(56, -1, "rip", SPECIAL);
 
-    public static final Register[] allRegisters = {
+    public static final RegisterArray allRegisters = new RegisterArray(
         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
@@ -162,7 +163,7 @@
         xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
         k0, k1, k2, k3, k4, k5, k6, k7,
         rip
-    };
+    );
 
     // @formatter:on
 
@@ -245,7 +246,7 @@
     }
 
     @Override
-    public Register[] getAvailableValueRegisters() {
+    public RegisterArray getAvailableValueRegisters() {
         if (features.contains(CPUFeature.AVX512F)) {
             return valueRegistersAVX512;
         } else {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Fri Jul 01 16:50:34 2016 -0700
@@ -23,7 +23,6 @@
 package jdk.vm.ci.code;
 
 import java.nio.ByteOrder;
-import java.util.Arrays;
 
 import jdk.vm.ci.code.Register.RegisterCategory;
 import jdk.vm.ci.meta.JavaKind;
@@ -46,10 +45,10 @@
     private final String name;
 
     /**
-     * Array of all available registers on this architecture. The index of each register in this
-     * array is equal to its {@linkplain Register#number number}.
+     * List of all available registers on this architecture. The index of each register in this list
+     * is equal to its {@linkplain Register#number number}.
      */
-    private final Register[] registers;
+    private final RegisterArray registers;
 
     /**
      * The byte ordering can be either little or big endian.
@@ -78,7 +77,8 @@
      */
     private final int returnAddressSize;
 
-    protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset,
+    protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, RegisterArray registers, int implicitMemoryBarriers,
+                    int nativeCallDisplacementOffset,
                     int returnAddressSize) {
         this.name = name;
         this.registers = registers;
@@ -120,20 +120,20 @@
     }
 
     /**
-     * Gets an array of all registers that exist on this architecture. This contains all registers
+     * Gets the list 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
+     * this particular architecture instance. The index of each register in this list is equal to
      * its {@linkplain Register#number number}.
      */
-    public Register[] getRegisters() {
-        return registers.clone();
+    public RegisterArray getRegisters() {
+        return registers;
     }
 
     /**
-     * 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.
+     * Gets a list 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() {
+    public RegisterArray getAvailableValueRegisters() {
         return getRegisters();
     }
 
@@ -206,7 +206,7 @@
                 assert this.byteOrder.equals(that.byteOrder);
                 assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
                 assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
-                assert Arrays.equals(this.registers, that.registers);
+                assert this.registers.equals(that.registers);
                 assert this.returnAddressSize == that.returnAddressSize;
                 assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
                 assert this.wordKind == that.wordKind;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java	Fri Jul 01 16:50:34 2016 -0700
@@ -34,7 +34,7 @@
  * where to find the local variables, operand stack values and locked objects of the bytecode
  * frame(s).
  */
-public class BytecodeFrame extends BytecodePosition {
+public final class BytecodeFrame extends BytecodePosition {
 
     /**
      * An array of values representing how to reconstruct the state of the Java frame. This is array
@@ -65,14 +65,18 @@
      * <p>
      * Note that the number of locals and the number of stack slots may be smaller than the maximum
      * number of locals and stack slots as specified in the compiled method.
+     *
+     * This field is intentionally exposed as a mutable array that a compiler may modify (e.g.
+     * during register allocation).
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "field is intentionally mutable")//
     public final JavaValue[] values;
 
     /**
-     * An array describing the Java kind of the {@link #values}. It records a kind for the locals
-     * and the operand stack.
+     * An array describing the Java kinds in {@link #values}. It records a kind for the locals and
+     * the operand stack.
      */
-    public final JavaKind[] slotKinds;
+    private final JavaKind[] slotKinds;
 
     /**
      * The number of locals in the values array.
@@ -99,8 +103,8 @@
     public final boolean rethrowException;
 
     /**
-     * Specifies if this object represents a frame state in the middle of executing a call. If
-     * true, the arguments to the call have been popped from the stack and the return value (for a
+     * Specifies if this object represents a frame state in the middle of executing a call. If true,
+     * the arguments to the call have been popped from the stack and the return value (for a
      * non-void call) has not yet been pushed.
      */
     public final boolean duringCall;
@@ -178,11 +182,14 @@
      * @param bci a BCI within the method
      * @param rethrowException specifies if the VM should re-throw the pending exception when
      *            deopt'ing using this frame
-     * @param values the frame state {@link #values}
+     * @param values the frame state {@link #values}.
+     * @param slotKinds the kinds in {@code values}. This array is now owned by this object and must
+     *            not be mutated by the caller.
      * @param numLocals the number of local variables
      * @param numStack the depth of the stack
      * @param numLocks the number of locked objects
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `slotKinds`")
     public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, JavaValue[] values, JavaKind[] slotKinds, int numLocals, int numStack,
                     int numLocks) {
         super(caller, method, bci);
@@ -219,12 +226,44 @@
     }
 
     /**
+     * Gets the kind of a local variable.
+     *
+     * @param i the local variable to query
+     * @return the kind of local variable {@code i}
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocals}
+     */
+    public JavaKind getLocalValueKind(int i) {
+        if (i < 0 || i >= numLocals) {
+            throw new IndexOutOfBoundsException();
+        }
+        return slotKinds[i];
+    }
+
+    /**
+     * Gets the kind of a stack slot.
+     *
+     * @param i the local variable to query
+     * @return the kind of stack slot {@code i}
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numStack}
+     */
+    public JavaKind getStackValueKind(int i) {
+        if (i < 0 || i >= numStack) {
+            throw new IndexOutOfBoundsException();
+        }
+        return slotKinds[i + numLocals];
+    }
+
+    /**
      * Gets the value representing the specified local variable.
      *
      * @param i the local variable index
      * @return the value that can be used to reconstruct the local's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocals}
      */
     public JavaValue getLocalValue(int i) {
+        if (i < 0 || i >= numLocals) {
+            throw new IndexOutOfBoundsException();
+        }
         return values[i];
     }
 
@@ -233,8 +272,12 @@
      *
      * @param i the stack index
      * @return the value that can be used to reconstruct the stack slot's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numStack}
      */
     public JavaValue getStackValue(int i) {
+        if (i < 0 || i >= numStack) {
+            throw new IndexOutOfBoundsException();
+        }
         return values[i + numLocals];
     }
 
@@ -243,8 +286,12 @@
      *
      * @param i the lock index
      * @return the value that can be used to reconstruct the lock's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocks}
      */
     public JavaValue getLockValue(int i) {
+        if (i < 0 || i >= numLocks) {
+            throw new IndexOutOfBoundsException();
+        }
         return values[i + numLocals + numStack];
     }
 
@@ -258,6 +305,11 @@
     }
 
     @Override
+    public int hashCode() {
+        return (numLocals + 1) ^ (numStack + 11) ^ (numLocks + 7);
+    }
+
+    @Override
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java	Fri Jul 01 16:50:34 2016 -0700
@@ -100,6 +100,7 @@
     /**
      * Gets the locations required for the arguments.
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "FB false positive")
     public AllocatableValue[] getArguments() {
         if (argumentLocations.length == 0) {
             return argumentLocations;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Fri Jul 01 16:50:34 2016 -0700
@@ -48,8 +48,10 @@
      *
      * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame
      *            frame} info
-     * @param virtualObjectMapping the mapping of {@link VirtualObject}s to their real values
+     * @param virtualObjectMapping the mapping of {@link VirtualObject}s to their real values. This
+     *            array is now owned by this object and must not be mutated by the caller.
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `virtualObjectMapping`")
     public DebugInfo(BytecodePosition codePos, VirtualObject[] virtualObjectMapping) {
         this.bytecodePosition = codePos;
         this.virtualObjectMapping = virtualObjectMapping;
--- /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/RegisterArray.java	Fri Jul 01 16:50:34 2016 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * An immutable ordered list of registers. Only required because Java lacks immutable arrays.
+ */
+public final class RegisterArray implements Iterable<Register> {
+
+    private final Register[] registers;
+    private int hash;
+
+    public RegisterArray(Register... registers) {
+        this.registers = registers;
+    }
+
+    public RegisterArray(Collection<Register> registers) {
+        this.registers = registers.toArray(new Register[registers.size()]);
+    }
+
+    /**
+     * Gets the number of registers.
+     */
+    public int size() {
+        return registers.length;
+    }
+
+    /**
+     * Gets the register at a given index.
+     *
+     * @param index the index of the register to retrieve
+     */
+    public Register get(int index) {
+        return registers[index];
+    }
+
+    public void addTo(Collection<Register> collection) {
+        collection.addAll(Arrays.asList(registers));
+    }
+
+    /**
+     * Gets an immutable view of the registers as a list.
+     */
+    public List<Register> asList() {
+        return Collections.unmodifiableList(Arrays.asList(registers));
+    }
+
+    /**
+     * Gets a copy of the registers as an array.
+     */
+    public Register[] toArray() {
+        return registers.clone();
+    }
+
+    public Iterator<Register> iterator() {
+        return Arrays.asList(registers).iterator();
+    }
+
+    @Override
+    public int hashCode() {
+        if (hash == 0 && registers.length > 0) {
+            hash = Arrays.hashCode(registers);
+        }
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof RegisterArray) {
+            return Arrays.equals(registers, ((RegisterArray) obj).registers);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(registers);
+    }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java	Fri Jul 01 16:50:34 2016 -0700
@@ -23,6 +23,8 @@
 package jdk.vm.ci.code;
 
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * A collection of register attributes. The specific attribute values for a register may be local to
@@ -53,13 +55,14 @@
      * @return an array whose length is the max register number in {@code registers} plus 1. An
      *         element at index i holds the attributes of the register whose number is i.
      */
-    public static RegisterAttributes[] createMap(RegisterConfig registerConfig, Register[] registers) {
-        RegisterAttributes[] map = new RegisterAttributes[registers.length];
+    public static RegisterAttributes[] createMap(RegisterConfig registerConfig, RegisterArray registers) {
+        RegisterAttributes[] map = new RegisterAttributes[registers.size()];
+        List<Register> callerSaveRegisters = registerConfig.getCallerSaveRegisters().asList();
+        List<Register> calleeSaveRegisters = registerConfig.getCalleeSaveRegisters() == null ? Collections.emptyList() : registerConfig.getCalleeSaveRegisters().asList();
+        List<Register> allocatableRegisters = registerConfig.getAllocatableRegisters().asList();
         for (Register reg : registers) {
             if (reg != null) {
-                Register[] csr = registerConfig.getCalleeSaveRegisters();
-                RegisterAttributes attr = new RegisterAttributes(Arrays.asList(registerConfig.getCallerSaveRegisters()).contains(reg), csr == null ? false : Arrays.asList(csr).contains(reg),
-                                Arrays.asList(registerConfig.getAllocatableRegisters()).contains(reg));
+                RegisterAttributes attr = new RegisterAttributes(callerSaveRegisters.contains(reg), calleeSaveRegisters.contains(reg), allocatableRegisters.contains(reg));
                 if (map.length <= reg.number) {
                     map = Arrays.copyOf(map, reg.number + 1);
                 }
@@ -75,23 +78,24 @@
     }
 
     /**
-     * @return Denotes a register that is available for use by a register allocator.
+     * @return {@code true} if a register is available for use by a register allocator otherwise
+     *         {@code false}
      */
     public boolean isAllocatable() {
         return allocatable;
     }
 
     /**
-     * @return Denotes a register whose value preservation (if required) across a call is the
-     *         responsibility of the callee.
+     * @return {@code true} if a register whose value preservation (if required) across a call is
+     *         the responsibility of the callee otherwise {@code false}
      */
     public boolean isCalleeSave() {
         return calleeSave;
     }
 
     /**
-     * @return Denotes a register whose value preservation (if required) across a call is the
-     *         responsibility of the caller.
+     * @return {@code true} if a register whose value preservation (if required) across a call is
+     *         the responsibility of the caller otherwise {@code false}
      */
     public boolean isCallerSave() {
         return callerSave;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -71,7 +71,7 @@
      * @return the ordered set of registers that may be used to pass parameters in a call conforming
      *         to {@code type}
      */
-    Register[] getCallingConventionRegisters(Type type, JavaKind kind);
+    RegisterArray getCallingConventionRegisters(Type type, JavaKind kind);
 
     /**
      * Gets the set of all registers that might be used by the register allocator.
@@ -80,23 +80,23 @@
      * {@link RegisterAllocationConfig#getAllocatableRegisters()}
      */
     @SuppressWarnings("javadoc")
-    Register[] getAllocatableRegisters();
+    RegisterArray getAllocatableRegisters();
 
     /**
      * Filters a set of registers and returns only those that can be used by the register allocator
      * for a value of a particular kind.
      */
-    Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers);
+    RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers);
 
     /**
      * Gets the registers whose values must be preserved by a method across any call it makes.
      */
-    Register[] getCallerSaveRegisters();
+    RegisterArray getCallerSaveRegisters();
 
     /**
      * Gets the registers whose values must be preserved by the callee.
      */
-    Register[] getCalleeSaveRegisters();
+    RegisterArray getCalleeSaveRegisters();
 
     /**
      * Gets a map from register {@linkplain Register#number numbers} to register
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java	Fri Jul 01 16:50:34 2016 -0700
@@ -50,6 +50,7 @@
      * @param registers the keys in the map
      * @param slots frame slot index for each register in {@code registers}
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `registers` and `slots`")
     public RegisterSaveLayout(Register[] registers, int[] slots) {
         assert registers.length == slots.length;
         this.registers = registers;
--- /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/SuppressFBWarnings.java	Fri Jul 01 16:50:34 2016 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+@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.code/src/jdk/vm/ci/code/VirtualObject.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java	Fri Jul 01 16:50:34 2016 -0700
@@ -119,17 +119,20 @@
     }
 
     /**
-     * Returns an array containing all the values to be stored into the object when it is recreated.
+     * Returns the array containing all the values to be stored into the object when it is
+     * recreated. This field is intentional exposed as a mutable array that a compiler may modify
+     * (e.g. during register allocation).
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "`values` is intentional mutable")//
     public JavaValue[] getValues() {
         return values;
     }
 
     /**
-     * Returns an array containing the Java kind of all values in the object.
+     * Returns the kind of the value at {@code index}.
      */
-    public JavaKind[] getSlotKinds() {
-        return slotKinds;
+    public JavaKind getSlotKind(int index) {
+        return slotKinds[index];
     }
 
     /**
@@ -145,9 +148,13 @@
      *
      * @param values an array containing all the values to be stored into the object when it is
      *            recreated.
-     * @param slotKinds an array containing the Java kinds of the values.
+     * @param slotKinds an array containing the Java kinds of the values. This must have the same
+     *            length as {@code values}. This array is now owned by this object and must not be
+     *            mutated by the caller.
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `slotKinds`")
     public void setValues(JavaValue[] values, JavaKind[] slotKinds) {
+        assert values.length == slotKinds.length;
         this.values = values;
         this.slotKinds = slotKinds;
     }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Fri Jul 01 16:50:34 2016 -0700
@@ -30,8 +30,8 @@
  * {@code "jvmci.inittimer"} system property to {@code "true"}.
  */
 public final class InitTimer implements AutoCloseable {
-    final String name;
-    final long start;
+    private final String name;
+    private final long start;
 
     private InitTimer(String name) {
         int n = nesting.getAndIncrement();
@@ -76,5 +76,5 @@
     /**
      * Used to assert the invariant that all related initialization happens on the same thread.
      */
-    public static Thread initializingThread;
+    static Thread initializingThread;
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java	Fri Jul 01 16:50:34 2016 -0700
@@ -38,24 +38,23 @@
 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.meta.ConstantReflectionProvider;
 import jdk.vm.ci.runtime.JVMCIBackend;
 
 public class AArch64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
 
-    protected EnumSet<AArch64.CPUFeature> computeFeatures(@SuppressWarnings("unused") HotSpotVMConfig config) {
+    protected EnumSet<AArch64.CPUFeature> computeFeatures(@SuppressWarnings("unused") AArch64HotSpotVMConfig config) {
         // Configure the feature set using the HotSpot flag settings.
         EnumSet<AArch64.CPUFeature> features = EnumSet.noneOf(AArch64.CPUFeature.class);
         return features;
     }
 
-    protected EnumSet<AArch64.Flag> computeFlags(@SuppressWarnings("unused") HotSpotVMConfig config) {
+    protected EnumSet<AArch64.Flag> computeFlags(@SuppressWarnings("unused") AArch64HotSpotVMConfig config) {
         EnumSet<AArch64.Flag> flags = EnumSet.noneOf(AArch64.Flag.class);
         return flags;
     }
 
-    protected TargetDescription createTarget(HotSpotVMConfig config) {
+    protected TargetDescription createTarget(AArch64HotSpotVMConfig config) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = true;
@@ -67,8 +66,8 @@
         return new HotSpotConstantReflectionProvider(runtime);
     }
 
-    protected RegisterConfig createRegisterConfig(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target) {
-        return new AArch64HotSpotRegisterConfig(target, runtime.getConfig());
+    protected RegisterConfig createRegisterConfig(AArch64HotSpotVMConfig config, TargetDescription target) {
+        return new AArch64HotSpotRegisterConfig(target, config.useCompressedOops);
     }
 
     protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
@@ -93,7 +92,8 @@
     public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
 
         assert host == null;
-        TargetDescription target = createTarget(runtime.getConfig());
+        AArch64HotSpotVMConfig config = new AArch64HotSpotVMConfig(runtime.getConfigStore());
+        TargetDescription target = createTarget(config);
 
         RegisterConfig regConfig;
         HotSpotCodeCacheProvider codeCache;
@@ -105,7 +105,7 @@
                 metaAccess = createMetaAccess(runtime);
             }
             try (InitTimer rt = timer("create RegisterConfig")) {
-                regConfig = createRegisterConfig(runtime, target);
+                regConfig = createRegisterConfig(config, target);
             }
             try (InitTimer rt = timer("create CodeCache provider")) {
                 codeCache = createCodeCache(runtime, target, regConfig);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -49,8 +49,6 @@
 import static jdk.vm.ci.aarch64.AArch64.zr;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -60,6 +58,7 @@
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CallingConvention.Type;
 import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.code.RegisterAttributes;
 import jdk.vm.ci.code.RegisterConfig;
 import jdk.vm.ci.code.StackSlot;
@@ -67,7 +66,6 @@
 import jdk.vm.ci.code.ValueKindFactory;
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
-import jdk.vm.ci.hotspot.HotSpotVMConfig;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
@@ -79,30 +77,24 @@
 
     private final TargetDescription target;
 
-    private final Register[] allocatable;
-
-    private final int maxFrameSize;
+    private final RegisterArray allocatable;
 
     /**
      * The caller saved registers always include all parameter registers.
      */
-    private final Register[] callerSaved;
+    private final RegisterArray callerSaved;
 
     private final boolean allAllocatableAreCallerSaved;
 
     private final RegisterAttributes[] attributesMap;
 
-    public int getMaximumFrameSize() {
-        return maxFrameSize;
+    @Override
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
     }
 
     @Override
-    public Register[] getAllocatableRegisters() {
-        return allocatable.clone();
-    }
-
-    @Override
-    public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : registers) {
             if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
@@ -110,8 +102,7 @@
             }
         }
 
-        Register[] ret = list.toArray(new Register[list.size()]);
-        return ret;
+        return new RegisterArray(list);
     }
 
     @Override
@@ -119,9 +110,9 @@
         return attributesMap.clone();
     }
 
-    private final Register[] javaGeneralParameterRegisters = {r1, r2, r3, r4, r5, r6, r7, r0};
-    private final Register[] nativeGeneralParameterRegisters = {r0, r1, r2, r3, r4, r5, r6, r7};
-    private final Register[] simdParameterRegisters = {v0, v1, v2, v3, v4, v5, v6, v7};
+    private final RegisterArray javaGeneralParameterRegisters = new RegisterArray(r1, r2, r3, r4, r5, r6, r7, r0);
+    private final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(r0, r1, r2, r3, r4, r5, r6, r7);
+    private final RegisterArray simdParameterRegisters = new RegisterArray(v0, v1, v2, v3, v4, v5, v6, v7);
 
     public static final Register inlineCacheRegister = r9;
 
@@ -134,12 +125,12 @@
     public static final Register threadRegister = r28;
     public static final Register fp = r29;
 
-    private static final Register[] reservedRegisters = {threadRegister, fp, lr, r31, zr, sp};
+    private static final RegisterArray reservedRegisters = new RegisterArray(threadRegister, fp, lr, r31, zr, sp);
 
-    private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
-        Register[] allRegisters = arch.getAvailableValueRegisters();
-        Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
-        List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
 
         int idx = 0;
         for (Register reg : allRegisters) {
@@ -157,36 +148,35 @@
         }
 
         assert idx == registers.length;
-        return registers;
+        return new RegisterArray(registers);
     }
 
-    public AArch64HotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
-        this(target, config, initAllocatable(target.arch, config.useCompressedOops));
-        assert callerSaved.length >= allocatable.length;
+    public AArch64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
+        this(target, initAllocatable(target.arch, useCompressedOops));
+        assert callerSaved.size() >= allocatable.size();
     }
 
-    public AArch64HotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config, Register[] allocatable) {
+    public AArch64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
         this.target = target;
-        this.maxFrameSize = config.maxFrameSize;
 
-        this.allocatable = allocatable.clone();
+        this.allocatable = allocatable;
         Set<Register> callerSaveSet = new HashSet<>();
-        Collections.addAll(callerSaveSet, allocatable);
-        Collections.addAll(callerSaveSet, simdParameterRegisters);
-        Collections.addAll(callerSaveSet, javaGeneralParameterRegisters);
-        Collections.addAll(callerSaveSet, nativeGeneralParameterRegisters);
-        callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
+        allocatable.addTo(callerSaveSet);
+        simdParameterRegisters.addTo(callerSaveSet);
+        javaGeneralParameterRegisters.addTo(callerSaveSet);
+        nativeGeneralParameterRegisters.addTo(callerSaveSet);
+        callerSaved = new RegisterArray(callerSaveSet);
 
         allAllocatableAreCallerSaved = true;
         attributesMap = RegisterAttributes.createMap(this, AArch64.allRegisters);
     }
 
     @Override
-    public Register[] getCallerSaveRegisters() {
+    public RegisterArray getCallerSaveRegisters() {
         return callerSaved;
     }
 
-    public Register[] getCalleeSaveRegisters() {
+    public RegisterArray getCalleeSaveRegisters() {
         return null;
     }
 
@@ -207,7 +197,7 @@
     }
 
     @Override
-    public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
         HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
         switch (kind) {
             case Boolean:
@@ -226,7 +216,7 @@
         }
     }
 
-    private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
                     ValueKindFactory<?> valueKindFactory) {
         AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 
@@ -245,15 +235,15 @@
                 case Int:
                 case Long:
                 case Object:
-                    if (currentGeneral < generalParameterRegisters.length) {
-                        Register register = generalParameterRegisters[currentGeneral++];
+                    if (currentGeneral < generalParameterRegisters.size()) {
+                        Register register = generalParameterRegisters.get(currentGeneral++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Float:
                 case Double:
-                    if (currentSIMD < simdParameterRegisters.length) {
-                        Register register = simdParameterRegisters[currentSIMD++];
+                    if (currentSIMD < simdParameterRegisters.size()) {
+                        Register register = simdParameterRegisters.get(currentSIMD++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
@@ -302,6 +292,6 @@
 
     @Override
     public String toString() {
-        return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.aarch64;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * Used to access native configuration details.
+ *
+ * All non-static, public fields in this class are so that they can be compiled as constants.
+ */
+class AArch64HotSpotVMConfig extends HotSpotVMConfigAccess {
+
+    AArch64HotSpotVMConfig(HotSpotVMConfigStore config) {
+        super(config);
+    }
+
+    final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
+
+    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java	Fri Jul 01 16:50:34 2016 -0700
@@ -38,13 +38,12 @@
 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.meta.ConstantReflectionProvider;
 import jdk.vm.ci.runtime.JVMCIBackend;
 
 public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
 
-    protected EnumSet<AMD64.CPUFeature> computeFeatures(HotSpotVMConfig config) {
+    protected EnumSet<AMD64.CPUFeature> computeFeatures(AMD64HotSpotVMConfig config) {
         // Configure the feature set using the HotSpot flag settings.
         EnumSet<AMD64.CPUFeature> features = EnumSet.noneOf(AMD64.CPUFeature.class);
         if ((config.vmVersionFeatures & config.amd643DNOWPREFETCH) != 0) {
@@ -128,7 +127,7 @@
         return features;
     }
 
-    protected EnumSet<AMD64.Flag> computeFlags(HotSpotVMConfig config) {
+    protected EnumSet<AMD64.Flag> computeFlags(AMD64HotSpotVMConfig config) {
         EnumSet<AMD64.Flag> flags = EnumSet.noneOf(AMD64.Flag.class);
         if (config.useCountLeadingZerosInstruction) {
             flags.add(AMD64.Flag.UseCountLeadingZerosInstruction);
@@ -139,7 +138,7 @@
         return flags;
     }
 
-    protected TargetDescription createTarget(HotSpotVMConfig config) {
+    protected TargetDescription createTarget(AMD64HotSpotVMConfig config) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = true;
@@ -151,8 +150,8 @@
         return new HotSpotConstantReflectionProvider(runtime);
     }
 
-    protected RegisterConfig createRegisterConfig(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target) {
-        return new AMD64HotSpotRegisterConfig(target, runtime.getConfig());
+    protected RegisterConfig createRegisterConfig(AMD64HotSpotVMConfig config, TargetDescription target) {
+        return new AMD64HotSpotRegisterConfig(target, config.useCompressedOops, config.windowsOs);
     }
 
     protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
@@ -175,9 +174,9 @@
 
     @SuppressWarnings("try")
     public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
-
         assert host == null;
-        TargetDescription target = createTarget(runtime.getConfig());
+        AMD64HotSpotVMConfig config = new AMD64HotSpotVMConfig(runtime.getConfigStore());
+        TargetDescription target = createTarget(config);
 
         RegisterConfig regConfig;
         HotSpotCodeCacheProvider codeCache;
@@ -189,7 +188,7 @@
                 metaAccess = createMetaAccess(runtime);
             }
             try (InitTimer rt = timer("create RegisterConfig")) {
-                regConfig = createRegisterConfig(runtime, target);
+                regConfig = createRegisterConfig(config, target);
             }
             try (InitTimer rt = timer("create CodeCache provider")) {
                 codeCache = createCodeCache(runtime, target, regConfig);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -42,8 +42,6 @@
 import static jdk.vm.ci.amd64.AMD64.xmm7;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -52,6 +50,7 @@
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CallingConvention.Type;
 import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.code.RegisterAttributes;
 import jdk.vm.ci.code.RegisterConfig;
 import jdk.vm.ci.code.StackSlot;
@@ -59,7 +58,6 @@
 import jdk.vm.ci.code.ValueKindFactory;
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
-import jdk.vm.ci.hotspot.HotSpotVMConfig;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
@@ -71,30 +69,24 @@
 
     private final TargetDescription target;
 
-    private final Register[] allocatable;
-
-    private final int maxFrameSize;
+    private final RegisterArray allocatable;
 
     /**
      * The caller saved registers always include all parameter registers.
      */
-    private final Register[] callerSaved;
+    private final RegisterArray callerSaved;
 
     private final boolean allAllocatableAreCallerSaved;
 
     private final RegisterAttributes[] attributesMap;
 
-    public int getMaximumFrameSize() {
-        return maxFrameSize;
+    @Override
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
     }
 
     @Override
-    public Register[] getAllocatableRegisters() {
-        return allocatable.clone();
-    }
-
-    @Override
-    public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : registers) {
             if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
@@ -102,7 +94,7 @@
             }
         }
 
-        Register[] ret = list.toArray(new Register[list.size()]);
+        RegisterArray ret = new RegisterArray(list);
         return ret;
     }
 
@@ -111,9 +103,9 @@
         return attributesMap.clone();
     }
 
-    private final Register[] javaGeneralParameterRegisters;
-    private final Register[] nativeGeneralParameterRegisters;
-    private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7};
+    private final RegisterArray javaGeneralParameterRegisters;
+    private final RegisterArray nativeGeneralParameterRegisters;
+    private final RegisterArray xmmParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
 
     /*
      * Some ABIs (e.g. Windows) require a so-called "home space", that is a save area on the stack
@@ -121,12 +113,12 @@
      */
     private final boolean needsNativeStackHomeSpace;
 
-    private static final Register[] reservedRegisters = {rsp, r15};
+    private static final RegisterArray reservedRegisters = new RegisterArray(rsp, r15);
 
-    private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
-        Register[] allRegisters = arch.getAvailableValueRegisters();
-        Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
-        List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
 
         int idx = 0;
         for (Register reg : allRegisters) {
@@ -143,47 +135,46 @@
         }
 
         assert idx == registers.length;
-        return registers;
+        return new RegisterArray(registers);
     }
 
-    public AMD64HotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
-        this(target, config, initAllocatable(target.arch, config.useCompressedOops));
-        assert callerSaved.length >= allocatable.length;
+    public AMD64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops, boolean windowsOs) {
+        this(target, initAllocatable(target.arch, useCompressedOops), windowsOs);
+        assert callerSaved.size() >= allocatable.size();
     }
 
-    public AMD64HotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config, Register[] allocatable) {
+    public AMD64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable, boolean windowsOs) {
         this.target = target;
-        this.maxFrameSize = config.maxFrameSize;
 
-        if (config.windowsOs) {
-            javaGeneralParameterRegisters = new Register[]{rdx, r8, r9, rdi, rsi, rcx};
-            nativeGeneralParameterRegisters = new Register[]{rcx, rdx, r8, r9};
+        if (windowsOs) {
+            javaGeneralParameterRegisters = new RegisterArray(rdx, r8, r9, rdi, rsi, rcx);
+            nativeGeneralParameterRegisters = new RegisterArray(rcx, rdx, r8, r9);
             this.needsNativeStackHomeSpace = true;
         } else {
-            javaGeneralParameterRegisters = new Register[]{rsi, rdx, rcx, r8, r9, rdi};
-            nativeGeneralParameterRegisters = new Register[]{rdi, rsi, rdx, rcx, r8, r9};
+            javaGeneralParameterRegisters = new RegisterArray(rsi, rdx, rcx, r8, r9, rdi);
+            nativeGeneralParameterRegisters = new RegisterArray(rdi, rsi, rdx, rcx, r8, r9);
             this.needsNativeStackHomeSpace = false;
         }
 
         this.allocatable = allocatable;
         Set<Register> callerSaveSet = new HashSet<>();
-        Collections.addAll(callerSaveSet, allocatable);
-        Collections.addAll(callerSaveSet, xmmParameterRegisters);
-        Collections.addAll(callerSaveSet, javaGeneralParameterRegisters);
-        Collections.addAll(callerSaveSet, nativeGeneralParameterRegisters);
-        callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
+        allocatable.addTo(callerSaveSet);
+        xmmParameterRegisters.addTo(callerSaveSet);
+        callerSaveSet.addAll(javaGeneralParameterRegisters.asList());
+        nativeGeneralParameterRegisters.addTo(callerSaveSet);
+        callerSaved = new RegisterArray(callerSaveSet);
 
         allAllocatableAreCallerSaved = true;
         attributesMap = RegisterAttributes.createMap(this, target.arch.getRegisters());
     }
 
     @Override
-    public Register[] getCallerSaveRegisters() {
+    public RegisterArray getCallerSaveRegisters() {
         return callerSaved;
     }
 
     @Override
-    public Register[] getCalleeSaveRegisters() {
+    public RegisterArray getCalleeSaveRegisters() {
         return null;
     }
 
@@ -204,7 +195,7 @@
     }
 
     @Override
-    public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
         HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
         switch (kind) {
             case Boolean:
@@ -223,13 +214,13 @@
         }
     }
 
-    private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
                     ValueKindFactory<?> valueKindFactory) {
         AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 
         int currentGeneral = 0;
         int currentXMM = 0;
-        int currentStackOffset = type == HotSpotCallingConventionType.NativeCall && needsNativeStackHomeSpace ? generalParameterRegisters.length * target.wordSize : 0;
+        int currentStackOffset = type == HotSpotCallingConventionType.NativeCall && needsNativeStackHomeSpace ? generalParameterRegisters.size() * target.wordSize : 0;
 
         for (int i = 0; i < parameterTypes.length; i++) {
             final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
@@ -242,15 +233,15 @@
                 case Int:
                 case Long:
                 case Object:
-                    if (currentGeneral < generalParameterRegisters.length) {
-                        Register register = generalParameterRegisters[currentGeneral++];
+                    if (currentGeneral < generalParameterRegisters.size()) {
+                        Register register = generalParameterRegisters.get(currentGeneral++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Float:
                 case Double:
-                    if (currentXMM < xmmParameterRegisters.length) {
-                        Register register = xmmParameterRegisters[currentXMM++];
+                    if (currentXMM < xmmParameterRegisters.size()) {
+                        Register register = xmmParameterRegisters.get(currentXMM++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
@@ -299,6 +290,6 @@
 
     @Override
     public String toString() {
-        return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.amd64;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess {
+
+    AMD64HotSpotVMConfig(HotSpotVMConfigStore config) {
+        super(config);
+    }
+
+    final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
+
+    final boolean useCountLeadingZerosInstruction = getFlag("UseCountLeadingZerosInstruction", Boolean.class);
+    final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class);
+    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
+
+    // CPU capabilities
+    final int useSSE = getFlag("UseSSE", Integer.class);
+    final int useAVX = getFlag("UseAVX", Integer.class);
+
+    final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t");
+
+    // CPU feature flags
+    final long amd64CX8 = getConstant("VM_Version::CPU_CX8", Long.class);
+    final long amd64CMOV = getConstant("VM_Version::CPU_CMOV", Long.class);
+    final long amd64FXSR = getConstant("VM_Version::CPU_FXSR", Long.class);
+    final long amd64HT = getConstant("VM_Version::CPU_HT", Long.class);
+    final long amd64MMX = getConstant("VM_Version::CPU_MMX", Long.class);
+    final long amd643DNOWPREFETCH = getConstant("VM_Version::CPU_3DNOW_PREFETCH", Long.class);
+    final long amd64SSE = getConstant("VM_Version::CPU_SSE", Long.class);
+    final long amd64SSE2 = getConstant("VM_Version::CPU_SSE2", Long.class);
+    final long amd64SSE3 = getConstant("VM_Version::CPU_SSE3", Long.class);
+    final long amd64SSSE3 = getConstant("VM_Version::CPU_SSSE3", Long.class);
+    final long amd64SSE4A = getConstant("VM_Version::CPU_SSE4A", Long.class);
+    final long amd64SSE41 = getConstant("VM_Version::CPU_SSE4_1", Long.class);
+    final long amd64SSE42 = getConstant("VM_Version::CPU_SSE4_2", Long.class);
+    final long amd64POPCNT = getConstant("VM_Version::CPU_POPCNT", Long.class);
+    final long amd64LZCNT = getConstant("VM_Version::CPU_LZCNT", Long.class);
+    final long amd64TSC = getConstant("VM_Version::CPU_TSC", Long.class);
+    final long amd64TSCINV = getConstant("VM_Version::CPU_TSCINV", Long.class);
+    final long amd64AVX = getConstant("VM_Version::CPU_AVX", Long.class);
+    final long amd64AVX2 = getConstant("VM_Version::CPU_AVX2", Long.class);
+    final long amd64AES = getConstant("VM_Version::CPU_AES", Long.class);
+    final long amd64ERMS = getConstant("VM_Version::CPU_ERMS", Long.class);
+    final long amd64CLMUL = getConstant("VM_Version::CPU_CLMUL", Long.class);
+    final long amd64BMI1 = getConstant("VM_Version::CPU_BMI1", Long.class);
+    final long amd64BMI2 = getConstant("VM_Version::CPU_BMI2", Long.class);
+    final long amd64RTM = getConstant("VM_Version::CPU_RTM", Long.class);
+    final long amd64ADX = getConstant("VM_Version::CPU_ADX", Long.class);
+    final long amd64AVX512F = getConstant("VM_Version::CPU_AVX512F", Long.class);
+    final long amd64AVX512DQ = getConstant("VM_Version::CPU_AVX512DQ", Long.class);
+    final long amd64AVX512PF = getConstant("VM_Version::CPU_AVX512PF", Long.class);
+    final long amd64AVX512ER = getConstant("VM_Version::CPU_AVX512ER", Long.class);
+    final long amd64AVX512CD = getConstant("VM_Version::CPU_AVX512CD", Long.class);
+    final long amd64AVX512BW = getConstant("VM_Version::CPU_AVX512BW", Long.class);
+    final long amd64AVX512VL = getConstant("VM_Version::CPU_AVX512VL", Long.class);
+    final long amd64SHA = getConstant("VM_Version::CPU_SHA", Long.class);
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Fri Jul 01 16:50:34 2016 -0700
@@ -37,14 +37,13 @@
 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.runtime.JVMCIBackend;
 import jdk.vm.ci.sparc.SPARC;
 import jdk.vm.ci.sparc.SPARC.CPUFeature;
 
 public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
 
-    protected TargetDescription createTarget(HotSpotVMConfig config) {
+    protected TargetDescription createTarget(SPARCHotSpotVMConfig config) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
         final boolean inlineObjects = false;
@@ -56,7 +55,7 @@
         return new HotSpotCodeCacheProvider(runtime, runtime.getConfig(), target, regConfig);
     }
 
-    protected EnumSet<CPUFeature> computeFeatures(HotSpotVMConfig config) {
+    protected EnumSet<CPUFeature> computeFeatures(SPARCHotSpotVMConfig config) {
         EnumSet<CPUFeature> features = EnumSet.noneOf(CPUFeature.class);
         if ((config.vmVersionFeatures & config.sparcVis1Instructions) != 0) {
             features.add(CPUFeature.VIS1);
@@ -143,10 +142,11 @@
     @SuppressWarnings("try")
     public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
         assert host == null;
-        TargetDescription target = createTarget(runtime.getConfig());
+        SPARCHotSpotVMConfig config = new SPARCHotSpotVMConfig(runtime.getConfigStore());
+        TargetDescription target = createTarget(config);
 
         HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
-        RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target, runtime.getConfig());
+        RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target, config.useCompressedOops);
         HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target, regConfig);
         HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
         StackIntrospection stackIntrospection = new HotSpotStackIntrospection(runtime);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -65,8 +65,6 @@
 import static jdk.vm.ci.sparc.SPARC.sp;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 
@@ -74,6 +72,7 @@
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CallingConvention.Type;
 import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.code.RegisterAttributes;
 import jdk.vm.ci.code.RegisterConfig;
 import jdk.vm.ci.code.StackSlot;
@@ -81,7 +80,6 @@
 import jdk.vm.ci.code.ValueKindFactory;
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
-import jdk.vm.ci.hotspot.HotSpotVMConfig;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
@@ -93,7 +91,7 @@
 
     private final TargetDescription target;
 
-    private final Register[] allocatable;
+    private final RegisterArray allocatable;
 
     private final RegisterAttributes[] attributesMap;
 
@@ -103,20 +101,19 @@
     private final boolean addNativeRegisterArgumentSlots;
 
     @Override
-    public Register[] getAllocatableRegisters() {
-        return allocatable.clone();
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
     }
 
     @Override
-    public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : registers) {
             if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
                 list.add(reg);
             }
         }
-        Register[] ret = list.toArray(new Register[list.size()]);
-        return ret;
+        return new RegisterArray(list);
     }
 
     @Override
@@ -124,30 +121,29 @@
         return attributesMap.clone();
     }
 
-    private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
-    private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
+    private final RegisterArray cpuCallerParameterRegisters = new RegisterArray(o0, o1, o2, o3, o4, o5);
+    private final RegisterArray cpuCalleeParameterRegisters = new RegisterArray(i0, i1, i2, i3, i4, i5);
 
-    private final Register[] fpuFloatParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
-    private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
+    private final RegisterArray fpuFloatParameterRegisters = new RegisterArray(f0, f1, f2, f3, f4, f5, f6, f7);
+    private final RegisterArray fpuDoubleParameterRegisters = new RegisterArray(d0, null, d2, null, d4, null, d6, null);
 
     // @formatter:off
-    private final Register[] callerSaveRegisters;
+    private final RegisterArray callerSaveRegisters;
 
     /**
-     * Registers saved by the callee. This lists all L and I registers which are saved in the
-     * register window.
+     * This lists all L and I registers which are saved in the register window.
      */
-    private final Register[] calleeSaveRegisters = {
+    private final RegisterArray windowSaveRegisters = new RegisterArray(
                     l0, l1, l2, l3, l4, l5, l6, l7,
-                    i0, i1, i2, i3, i4, i5, i6, i7};
+                    i0, i1, i2, i3, i4, i5, i6, i7);
     // @formatter:on
 
-    private static final Register[] reservedRegisters = {sp, g0, g2};
+    private static final RegisterArray reservedRegisters = new RegisterArray(sp, g0, g2);
 
-    private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
-        Register[] allRegisters = arch.getAvailableValueRegisters();
-        Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
-        List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
 
         int idx = 0;
         for (Register reg : allRegisters) {
@@ -164,33 +160,33 @@
         }
 
         assert idx == registers.length;
-        return registers;
+        return new RegisterArray(registers);
     }
 
-    public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
-        this(target, initAllocatable(target.arch, config.useCompressedOops), config);
+    public SPARCHotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
+        this(target, initAllocatable(target.arch, useCompressedOops));
     }
 
-    public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable, HotSpotVMConfig config) {
+    public SPARCHotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
         this.target = target;
-        this.allocatable = allocatable.clone();
-        this.addNativeRegisterArgumentSlots = config.linuxOs;
-        HashSet<Register> callerSaveSet = new HashSet<>();
-        Collections.addAll(callerSaveSet, target.arch.getAvailableValueRegisters());
-        for (Register cs : calleeSaveRegisters) {
+        this.allocatable = allocatable;
+        this.addNativeRegisterArgumentSlots = false;
+        HashSet<Register> callerSaveSet = new HashSet<>(target.arch.getAvailableValueRegisters().asList());
+        for (Register cs : windowSaveRegisters) {
             callerSaveSet.remove(cs);
         }
-        this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
+        this.callerSaveRegisters = new RegisterArray(callerSaveSet);
         attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
     }
 
     @Override
-    public Register[] getCallerSaveRegisters() {
+    public RegisterArray getCallerSaveRegisters() {
         return callerSaveRegisters;
     }
 
-    public Register[] getCalleeSaveRegisters() {
-        return calleeSaveRegisters;
+    @Override
+    public RegisterArray getCalleeSaveRegisters() {
+        return null;
     }
 
     @Override
@@ -211,7 +207,7 @@
     }
 
     @Override
-    public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
         HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
         switch (kind) {
             case Boolean:
@@ -230,7 +226,7 @@
         }
     }
 
-    private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
                     ValueKindFactory<?> valueKindFactory) {
         AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 
@@ -249,25 +245,25 @@
                 case Int:
                 case Long:
                 case Object:
-                    if (currentGeneral < generalParameterRegisters.length) {
-                        Register register = generalParameterRegisters[currentGeneral++];
+                    if (currentGeneral < generalParameterRegisters.size()) {
+                        Register register = generalParameterRegisters.get(currentGeneral++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Double:
-                    if (currentFloating < fpuFloatParameterRegisters.length) {
+                    if (currentFloating < fpuFloatParameterRegisters.size()) {
                         if (currentFloating % 2 != 0) {
                             // Make register number even to be a double reg
                             currentFloating++;
                         }
-                        Register register = fpuDoubleParameterRegisters[currentFloating];
+                        Register register = fpuDoubleParameterRegisters.get(currentFloating);
                         currentFloating += 2; // Only every second is a double register
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Float:
-                    if (currentFloating < fpuFloatParameterRegisters.length) {
-                        Register register = fpuFloatParameterRegisters[currentFloating++];
+                    if (currentFloating < fpuFloatParameterRegisters.size()) {
+                        Register register = fpuFloatParameterRegisters.get(currentFloating++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
@@ -292,7 +288,7 @@
         int outArgSpillArea;
         if (type == HotSpotCallingConventionType.NativeCall && addNativeRegisterArgumentSlots) {
             // Space for native callee which may spill our outgoing arguments
-            outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize;
+            outArgSpillArea = Math.min(locations.length, generalParameterRegisters.size()) * target.wordSize;
         } else {
             outArgSpillArea = 0;
         }
@@ -337,6 +333,6 @@
 
     @Override
     public String toString() {
-        return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sparc;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * Used to access native configuration details.
+ *
+ * All non-static, public fields in this class are so that they can be compiled as constants.
+ */
+class SPARCHotSpotVMConfig extends HotSpotVMConfigAccess {
+
+    SPARCHotSpotVMConfig(HotSpotVMConfigStore config) {
+        super(config);
+    }
+
+    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
+
+    // CPU capabilities
+    final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t");
+
+    // SPARC specific values
+    final int sparcVis3Instructions = getConstant("VM_Version::vis3_instructions_m", Integer.class);
+    final int sparcVis2Instructions = getConstant("VM_Version::vis2_instructions_m", Integer.class);
+    final int sparcVis1Instructions = getConstant("VM_Version::vis1_instructions_m", Integer.class);
+    final int sparcCbcondInstructions = getConstant("VM_Version::cbcond_instructions_m", Integer.class);
+    final int sparcV8Instructions = getConstant("VM_Version::v8_instructions_m", Integer.class);
+    final int sparcHardwareMul32 = getConstant("VM_Version::hardware_mul32_m", Integer.class);
+    final int sparcHardwareDiv32 = getConstant("VM_Version::hardware_div32_m", Integer.class);
+    final int sparcHardwareFsmuld = getConstant("VM_Version::hardware_fsmuld_m", Integer.class);
+    final int sparcHardwarePopc = getConstant("VM_Version::hardware_popc_m", Integer.class);
+    final int sparcV9Instructions = getConstant("VM_Version::v9_instructions_m", Integer.class);
+    final int sparcSun4v = getConstant("VM_Version::sun4v_m", Integer.class);
+    final int sparcBlkInitInstructions = getConstant("VM_Version::blk_init_instructions_m", Integer.class);
+    final int sparcFmafInstructions = getConstant("VM_Version::fmaf_instructions_m", Integer.class);
+    final int sparcFmauInstructions = getConstant("VM_Version::fmau_instructions_m", Integer.class);
+    final int sparcSparc64Family = getConstant("VM_Version::sparc64_family_m", Integer.class);
+    final int sparcMFamily = getConstant("VM_Version::M_family_m", Integer.class);
+    final int sparcTFamily = getConstant("VM_Version::T_family_m", Integer.class);
+    final int sparcT1Model = getConstant("VM_Version::T1_model_m", Integer.class);
+    final int sparcSparc5Instructions = getConstant("VM_Version::sparc5_instructions_m", Integer.class);
+    final int sparcAesInstructions = getConstant("VM_Version::aes_instructions_m", Integer.class);
+    final int sparcSha1Instruction = getConstant("VM_Version::sha1_instruction_m", Integer.class);
+    final int sparcSha256Instruction = getConstant("VM_Version::sha256_instruction_m", Integer.class);
+    final int sparcSha512Instruction = getConstant("VM_Version::sha512_instruction_m", Integer.class);
+
+    final boolean useBlockZeroing = getFlag("UseBlockZeroing", Boolean.class);
+    final int blockZeroingLowLimit = getFlag("BlockZeroingLowLimit", Integer.class);
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Jul 01 16:50:34 2016 -0700
@@ -35,11 +35,9 @@
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.common.JVMCIError;
-import jdk.vm.ci.hotspotvmconfig.HotSpotVMField;
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.internal.misc.Unsafe;
 
 /**
  * Calls from Java into HotSpot. The behavior of all the methods in this class that take a native
@@ -267,8 +265,9 @@
     native HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool, int cpi) throws LinkageError;
 
     /**
-     * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry at index {@code cpi} in
-     * {@code constantPool}. The values returned in {@code info} are:
+     * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry for at index {@code cpi} in
+     * {@code constantPool}. For some opcodes, checks are performed that require the {@code method}
+     * that contains {@code opcode} to be specified. The values returned in {@code info} are:
      *
      * <pre>
      *     [(int) flags,   // only valid if field is resolved
@@ -281,7 +280,7 @@
      * @param info an array in which the details of the field are returned
      * @return the type defining the field if resolution is successful, 0 otherwise
      */
-    native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, byte opcode, long[] info);
+    native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, HotSpotResolvedJavaMethodImpl method, byte opcode, long[] info);
 
     /**
      * Converts {@code cpci} from an index into the cache for {@code constantPool} to an index
@@ -338,9 +337,22 @@
     native void resetCompilationStatistics();
 
     /**
-     * Initializes the fields of {@code config}.
+     * Reads the database of VM info. The return value encodes the info in a nested object array
+     * that is described by the pseudo Java object {@code info} below:
+     *
+     * <pre>
+     *     info = [
+     *         VMField[] vmFields,
+     *         [String name, Long size, ...] vmTypeSizes,
+     *         [String name, Long value, ...] vmConstants,
+     *         [String name, Long value, ...] vmAddresses,
+     *         VMFlag[] vmFlags
+     *     ]
+     * </pre>
+     *
+     * @return VM info as encoded above
      */
-    native long initializeConfiguration(HotSpotVMConfig config);
+    native Object[] readConfiguration();
 
     /**
      * Resolves the implementation of {@code method} for virtual dispatches on objects of dynamic
@@ -428,7 +440,6 @@
      * <li>{@link HotSpotVMConfig#localVariableTableElementLengthOffset}</li>
      * <li>{@link HotSpotVMConfig#localVariableTableElementNameCpIndexOffset}</li>
      * <li>{@link HotSpotVMConfig#localVariableTableElementDescriptorCpIndexOffset}</li>
-     * <li>{@link HotSpotVMConfig#localVariableTableElementSignatureCpIndexOffset}
      * <li>{@link HotSpotVMConfig#localVariableTableElementSlotOffset}
      * <li>{@link HotSpotVMConfig#localVariableTableElementStartBciOffset}
      * </ul>
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Fri Jul 01 16:50:34 2016 -0700
@@ -42,7 +42,7 @@
 public class HotSpotCodeCacheProvider implements CodeCacheProvider {
 
     protected final HotSpotJVMCIRuntimeProvider runtime;
-    public final HotSpotVMConfig config;
+    protected final HotSpotVMConfig config;
     protected final TargetDescription target;
     protected final RegisterConfig regConfig;
 
@@ -80,12 +80,13 @@
         for (Field f : fields) {
             if (f.getName().endsWith("Stub")) {
                 f.setAccessible(true);
+                Object address;
                 try {
-                    Object address = f.get(runtime.getConfig());
+                    address = f.get(runtime.getConfig());
                     if (address.equals(call.target)) {
                         return f.getName() + ":0x" + Long.toHexString((Long) address);
                     }
-                } catch (Exception e) {
+                } catch (IllegalArgumentException | IllegalAccessException e) {
                 }
             }
         }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java	Fri Jul 01 16:50:34 2016 -0700
@@ -115,6 +115,7 @@
         }
     }
 
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `sites`, `targetCode`, `comments`, `methods`, `dataSection`, `dataSectionPatches` and `assumptions`")
     public HotSpotCompiledCode(String name, byte[] targetCode, int targetCodeSize, Site[] sites, Assumption[] assumptions, ResolvedJavaMethod[] methods, Comment[] comments, byte[] dataSection,
                     int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, StackSlot deoptRescueSlot) {
         this.name = name;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Fri Jul 01 16:50:34 2016 -0700
@@ -196,7 +196,9 @@
      */
     @SuppressWarnings("unused")
     private static HotSpotConstantPool fromMetaspace(long metaspaceConstantPool) {
-        return new HotSpotConstantPool(metaspaceConstantPool);
+        HotSpotConstantPool cp = new HotSpotConstantPool(metaspaceConstantPool);
+        runtime().metaAccessContext.add(cp);
+        return cp;
     }
 
     private HotSpotConstantPool(long metaspaceConstantPool) {
@@ -298,7 +300,8 @@
      */
     private long getEntryAt(int index) {
         assertBounds(index);
-        return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -309,7 +312,8 @@
      */
     private int getIntAt(int index) {
         assertTag(index, JVM_CONSTANT.Integer);
-        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -320,7 +324,8 @@
      */
     private long getLongAt(int index) {
         assertTag(index, JVM_CONSTANT.Long);
-        return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -331,7 +336,8 @@
      */
     private float getFloatAt(int index) {
         assertTag(index, JVM_CONSTANT.Float);
-        return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -342,7 +348,8 @@
      */
     private double getDoubleAt(int index) {
         assertTag(index, JVM_CONSTANT.Double);
-        return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -353,7 +360,8 @@
      */
     private int getNameAndTypeAt(int index) {
         assertTag(index, JVM_CONSTANT.NameAndType);
-        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -434,7 +442,8 @@
      */
     private int getUncachedKlassRefIndexAt(int index) {
         assertTagIsFieldOrMethod(index);
-        final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
         // klass ref index is in the low 16-bits.
         return refIndex & 0xFFFF;
     }
@@ -587,7 +596,7 @@
     }
 
     @Override
-    public JavaField lookupField(int cpi, int opcode) {
+    public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
         final int index = rawIndexToConstantPoolIndex(cpi, opcode);
         final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
         final int nameIndex = getNameRefIndexAt(nameAndTypeIndex);
@@ -603,7 +612,7 @@
             long[] info = new long[2];
             HotSpotResolvedObjectTypeImpl resolvedHolder;
             try {
-                resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (byte) opcode, info);
+                resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
             } catch (Throwable t) {
                 /*
                  * If there was an exception resolving the field we give up and return an unresolved
@@ -680,15 +689,15 @@
                 if (!klass.isPrimitive() && !klass.isArray()) {
                     UNSAFE.ensureClassInitialized(klass);
                 }
-                switch (tag) {
-                    case MethodRef:
-                        if (Bytecodes.isInvokeHandleAlias(opcode)) {
-                            final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
-                            if (isInvokeHandle(methodRefCacheIndex, type)) {
-                                compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
-                            }
+                if (tag == JVM_CONSTANT.MethodRef) {
+                    if (Bytecodes.isInvokeHandleAlias(opcode)) {
+                        final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
+                        if (isInvokeHandle(methodRefCacheIndex, type)) {
+                            compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
                         }
+                    }
                 }
+
                 break;
             case InvokeDynamic:
                 if (isInvokedynamicIndex(cpi)) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java	Fri Jul 01 16:50:34 2016 -0700
@@ -25,7 +25,6 @@
 import java.lang.reflect.Array;
 import java.util.Objects;
 
-import jdk.internal.vm.annotation.Stable;
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java	Fri Jul 01 16:50:34 2016 -0700
@@ -29,6 +29,7 @@
     /**
      * The entry point address of this call's target.
      */
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "accessed by subclasses")//
     protected long address;
 
     public HotSpotForeignCallTarget(long address) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -22,8 +22,6 @@
  */
 package jdk.vm.ci.hotspot;
 
-import java.lang.reflect.Module;
-
 import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
@@ -68,7 +66,6 @@
             if (compilerName != null) {
                 for (JVMCICompilerFactory f : Services.load(JVMCICompilerFactory.class)) {
                     if (f.getCompilerName().equals(compilerName)) {
-                        Module jvmciModule = JVMCICompilerFactory.class.getModule();
                         Services.exportJVMCITo(f.getClass());
                         f.onSelection();
                         factory = f;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIMetaAccessContext.java	Fri Jul 01 16:50:34 2016 -0700
@@ -135,6 +135,7 @@
              */
             metadataRoots = list.getHead();
         }
+        assert isRegistered(metaspaceObject);
     }
 
     protected ResolvedJavaType createClass(Class<?> javaClass) {
@@ -208,7 +209,7 @@
             ChunkIterator() {
                 currentChunk = head;
                 currentIndex = -1;
-                findNext();
+                next = findNext();
             }
 
             Object[] currentChunk;
@@ -245,4 +246,13 @@
         }
 
     }
+
+    synchronized boolean isRegistered(MetaspaceWrapperObject wrapper) {
+        for (WeakReference<MetaspaceWrapperObject> m : list) {
+            if (m != null && m.get() == wrapper) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Fri Jul 01 16:50:34 2016 -0700
@@ -27,10 +27,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -48,6 +44,7 @@
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory;
+import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory.CompilationLevel;
 import jdk.vm.ci.hotspot.services.HotSpotVMEventListener;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
@@ -94,9 +91,10 @@
      */
     public enum Option {
         Compiler(String.class, null, "Selects the system compiler."),
-        // Note: The following one is not used (see InitTimer.ENABLED).
+        // Note: The following one is not used (see InitTimer.ENABLED). It is added here
+        // so that -Djvmci.PrintFlags=true shows the option.
         InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."),
-        PrintConfig(boolean.class, false, "Prints all HotSpotVMConfig fields."),
+        PrintConfig(boolean.class, false, "Prints VM configuration available via JVMCI and exits."),
         PrintFlags(boolean.class, false, "Prints all JVMCI flags and exits."),
         ShowFlags(boolean.class, false, "Prints all JVMCI flags and continues."),
         TraceMethodDataFilter(String.class, null, "");
@@ -200,6 +198,7 @@
 
     protected final CompilerToVM compilerToVm;
 
+    protected final HotSpotVMConfigStore configStore;
     protected final HotSpotVMConfig config;
     private final JVMCIBackend hostBackend;
 
@@ -240,11 +239,13 @@
     @SuppressWarnings("unused") private final String[] trivialPrefixes;
 
     @SuppressWarnings("try")
+    @SuppressFBWarnings(value = "DM_EXIT", justification = "PrintFlags is meant to exit the VM")
     private HotSpotJVMCIRuntime() {
         compilerToVm = new CompilerToVM();
 
         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
-            config = new HotSpotVMConfig(compilerToVm);
+            configStore = new HotSpotVMConfigStore(compilerToVm);
+            config = new HotSpotVMConfig(configStore);
         }
 
         String hostArchitecture = config.getHostArchitectureName();
@@ -270,18 +271,32 @@
         }
 
         if (Option.PrintConfig.getBoolean()) {
-            printConfig(config, compilerToVm);
+            printConfig(configStore, compilerToVm);
+            System.exit(0);
         }
 
         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
             trivialPrefixes = hsCompilerFactory.getTrivialPrefixes();
-            compilationLevelAdjustment = hsCompilerFactory.getCompilationLevelAdjustment(config);
+            switch (hsCompilerFactory.getCompilationLevelAdjustment()) {
+                case None:
+                    compilationLevelAdjustment = config.compLevelAdjustmentNone;
+                    break;
+                case ByHolder:
+                    compilationLevelAdjustment = config.compLevelAdjustmentByHolder;
+                    break;
+                case ByFullSignature:
+                    compilationLevelAdjustment = config.compLevelAdjustmentByFullSignature;
+                    break;
+                default:
+                    compilationLevelAdjustment = config.compLevelAdjustmentNone;
+                    break;
+            }
         } else {
             hsCompilerFactory = null;
             trivialPrefixes = null;
-            compilationLevelAdjustment = 0;
+            compilationLevelAdjustment = config.compLevelAdjustmentNone;
         }
     }
 
@@ -296,6 +311,10 @@
         return metaAccessContext.fromClass(javaClass);
     }
 
+    public HotSpotVMConfigStore getConfigStore() {
+        return configStore;
+    }
+
     public HotSpotVMConfig getConfig() {
         return config;
     }
@@ -352,7 +371,35 @@
      */
     @SuppressWarnings({"unused"})
     private int adjustCompilationLevel(Class<?> declaringClass, String name, String signature, boolean isOsr, int level) {
-        return hsCompilerFactory.adjustCompilationLevel(config, declaringClass, name, signature, isOsr, level);
+        CompilationLevel curLevel;
+        if (level == config.compilationLevelNone) {
+            curLevel = CompilationLevel.None;
+        } else if (level == config.compilationLevelSimple) {
+            curLevel = CompilationLevel.Simple;
+        } else if (level == config.compilationLevelLimitedProfile) {
+            curLevel = CompilationLevel.LimitedProfile;
+        } else if (level == config.compilationLevelFullProfile) {
+            curLevel = CompilationLevel.FullProfile;
+        } else if (level == config.compilationLevelFullOptimization) {
+            curLevel = CompilationLevel.FullOptimization;
+        } else {
+            throw JVMCIError.shouldNotReachHere();
+        }
+
+        switch (hsCompilerFactory.adjustCompilationLevel(declaringClass, name, signature, isOsr, curLevel)) {
+            case None:
+                return config.compilationLevelNone;
+            case Simple:
+                return config.compilationLevelSimple;
+            case LimitedProfile:
+                return config.compilationLevelLimitedProfile;
+            case FullProfile:
+                return config.compilationLevelFullProfile;
+            case FullOptimization:
+                return config.compilationLevelFullOptimization;
+            default:
+                return level;
+        }
     }
 
     /**
@@ -416,71 +463,40 @@
         }
     }
 
-    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);
+    @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
+    private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
+        String line = String.format(format, args);
+        byte[] lineBytes = line.getBytes();
+        vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
+        vm.flushDebugOutput();
+    }
+
+    private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
+        TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
+        for (VMField field : fields.values()) {
+            if (!field.isStatic()) {
+                printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
+            } else {
+                String value = field.value == null ? "null" : String.format("%d[0x%x]", field.value, field.value);
+                printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
             }
         }
-        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) {
-            }
+        TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
+        for (VMFlag flag : flags.values()) {
+            printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
         }
-    }
-
-    private static String pretty(Object value) {
-        if (value == null) {
-            return "null";
+        TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
+        for (Map.Entry<String, Long> e : addresses.entrySet()) {
+            printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
         }
-
-        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();
+        TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
+        for (Map.Entry<String, Long> e : constants.entrySet()) {
+            printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
         }
-        return value.toString();
+        TreeMap<String, Long> typeSizes = new TreeMap<>(store.getTypeSizes());
+        for (Map.Entry<String, Long> e : typeSizes.entrySet()) {
+            printConfigLine(vm, "[vmconfig:type size] %s = %d%n", e.getKey(), e.getValue());
+        }
     }
 
     public OutputStream getLogStream() {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntimeProvider.java	Fri Jul 01 16:50:34 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,6 +36,8 @@
  */
 public interface HotSpotJVMCIRuntimeProvider extends JVMCIRuntime {
 
+    HotSpotVMConfigStore getConfigStore();
+
     HotSpotVMConfig getConfig();
 
     CompilerToVM getCompilerToVM();
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProvider.java	Fri Jul 01 16:50:34 2016 -0700
@@ -22,7 +22,6 @@
  */
 package jdk.vm.ci.hotspot;
 
-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;
@@ -32,11 +31,11 @@
  */
 public interface HotSpotMemoryAccessProvider extends MemoryAccessProvider {
 
-    JavaConstant readNarrowOopConstant(Constant base, long displacement, CompressEncoding encoding);
+    JavaConstant readNarrowOopConstant(Constant base, long displacement);
 
     Constant readKlassPointerConstant(Constant base, long displacement);
 
-    Constant readNarrowKlassPointerConstant(Constant base, long displacement, CompressEncoding encoding);
+    Constant readNarrowKlassPointerConstant(Constant base, long displacement);
 
     Constant readMethodPointerConstant(Constant base, long displacement);
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java	Fri Jul 01 16:50:34 2016 -0700
@@ -23,7 +23,7 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
-import jdk.vm.ci.hotspot.HotSpotVMConfig.CompressEncoding;
+
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
@@ -206,8 +206,7 @@
     }
 
     @Override
-    public JavaConstant readNarrowOopConstant(Constant base, long displacement, CompressEncoding encoding) {
-        assert encoding.equals(runtime.getConfig().getOopEncoding()) : "unexpected oop encoding: " + encoding + " != " + runtime.getConfig().getOopEncoding();
+    public JavaConstant readNarrowOopConstant(Constant base, long displacement) {
         return HotSpotObjectConstantImpl.forObject(readRawObject(base, displacement, true), true);
     }
 
@@ -227,7 +226,7 @@
     }
 
     @Override
-    public Constant readNarrowKlassPointerConstant(Constant base, long displacement, CompressEncoding encoding) {
+    public Constant readNarrowKlassPointerConstant(Constant base, long displacement) {
         HotSpotResolvedObjectTypeImpl klass = readKlass(base, displacement, true);
         if (klass == null) {
             return HotSpotCompressedNullConstant.COMPRESSED_NULL;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Fri Jul 01 16:50:34 2016 -0700
@@ -30,7 +30,7 @@
 
 import java.util.Arrays;
 
-import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.Tag;
+import jdk.internal.misc.Unsafe;
 import jdk.vm.ci.meta.DeoptimizationReason;
 import jdk.vm.ci.meta.JavaMethodProfile;
 import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod;
@@ -39,41 +39,20 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.TriState;
-import jdk.internal.misc.Unsafe;
 
 /**
- * Access to a HotSpot MethodData structure (defined in methodData.hpp).
+ * Access to a HotSpot {@code MethodData} structure (defined in methodData.hpp).
  */
-public final class HotSpotMethodData {
+final class HotSpotMethodData {
 
-    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);
-
-    // sorted by tag
-    // @formatter:off
-    private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
-        null,
-        new BitData(),
-        new CounterData(),
-        new JumpData(),
-        new ReceiverTypeData(),
-        new VirtualCallData(),
-        new RetData(),
-        new BranchData(),
-        new MultiBranchData(),
-        new ArgInfoData(),
-        new UnknownProfileData(Tag.CallTypeData),
-        new VirtualCallTypeData(),
-        new UnknownProfileData(Tag.ParametersTypeData),
-        new UnknownProfileData(Tag.SpeculativeTrapData),
-    };
-    // @formatter:on
+    static final HotSpotVMConfig config = config();
+    static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.FALSE);
+    static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.UNKNOWN);
 
     /**
      * Reference to the C++ MethodData object.
      */
-    private final long metaspaceMethodData;
+    final long metaspaceMethodData;
     @SuppressWarnings("unused") private final HotSpotResolvedJavaMethodImpl method;
 
     public HotSpotMethodData(long metaspaceMethodData, HotSpotResolvedJavaMethodImpl method) {
@@ -133,10 +112,7 @@
             return null;
         }
 
-        HotSpotMethodDataAccessor result = getData(position);
-        final Tag tag = AbstractMethodData.readTag(this, position);
-        assert result != null : "NO_DATA tag is not allowed " + tag;
-        return result;
+        return getData(position);
     }
 
     public HotSpotMethodDataAccessor getExtraData(int position) {
@@ -160,18 +136,18 @@
 
     private HotSpotMethodDataAccessor getData(int position) {
         assert position >= 0 : "out of bounds";
-        final Tag tag = AbstractMethodData.readTag(this, position);
-        HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag.getValue()];
+        final int tag = HotSpotMethodDataAccessor.readTag(config, this, position);
+        HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag];
         assert accessor == null || accessor.getTag() == tag : "wrong data accessor " + accessor + " for tag " + tag;
         return accessor;
     }
 
-    private int readUnsignedByte(int position, int offsetInBytes) {
+    int readUnsignedByte(int position, int offsetInBytes) {
         long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
         return UNSAFE.getByte(metaspaceMethodData + fullOffsetInBytes) & 0xFF;
     }
 
-    private int readUnsignedShort(int position, int offsetInBytes) {
+    int readUnsignedShort(int position, int offsetInBytes) {
         long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
         return UNSAFE.getShort(metaspaceMethodData + fullOffsetInBytes) & 0xFFFF;
     }
@@ -269,102 +245,14 @@
         return sb.toString();
     }
 
-    private abstract static class AbstractMethodData implements HotSpotMethodDataAccessor {
+    static final int NO_DATA_SIZE = cellIndexToOffset(0);
 
-        /**
-         * Corresponds to {@code exception_seen_flag}.
-         */
-        private static final int EXCEPTIONS_MASK = 1 << config.bitDataExceptionSeenFlag;
-
-        private final Tag tag;
-        protected final int staticSize;
-
-        protected AbstractMethodData(Tag tag, int staticSize) {
-            this.tag = tag;
-            this.staticSize = staticSize;
-        }
-
-        public Tag getTag() {
-            return tag;
-        }
-
-        public static Tag readTag(HotSpotMethodData data, int position) {
-            final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
-            return Tag.getEnum(tag);
-        }
-
-        @Override
-        public int getBCI(HotSpotMethodData data, int position) {
-            return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
-        }
-
-        @Override
-        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
-        public TriState getExceptionSeen(HotSpotMethodData data, int position) {
-            return TriState.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0);
-        }
-
-        @Override
-        public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
-            return null;
-        }
-
-        @Override
-        public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
-            return null;
-        }
-
-        @Override
-        public double getBranchTakenProbability(HotSpotMethodData data, int position) {
-            return -1;
-        }
-
-        @Override
-        public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
-            return null;
-        }
-
-        @Override
-        public int getExecutionCount(HotSpotMethodData data, int position) {
-            return -1;
-        }
-
-        @Override
-        public TriState getNullSeen(HotSpotMethodData data, int position) {
-            return TriState.UNKNOWN;
-        }
-
-        protected int getFlags(HotSpotMethodData data, int position) {
-            return data.readUnsignedByte(position, config.dataLayoutFlagsOffset);
-        }
-
-        /**
-         * @param data
-         * @param position
-         */
-        protected int getDynamicSize(HotSpotMethodData data, int position) {
-            return 0;
-        }
-
-        public abstract StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
-    }
-
-    private static class NoMethodData extends AbstractMethodData {
-
-        private static final int NO_DATA_SIZE = cellIndexToOffset(0);
+    static class NoMethodData extends HotSpotMethodDataAccessor {
 
         private final TriState exceptionSeen;
 
-        protected NoMethodData(TriState exceptionSeen) {
-            super(Tag.No, NO_DATA_SIZE);
+        protected NoMethodData(HotSpotVMConfig config, int tag, TriState exceptionSeen) {
+            super(config, tag, NO_DATA_SIZE);
             this.exceptionSeen = exceptionSeen;
         }
 
@@ -384,17 +272,17 @@
         }
     }
 
-    private static class BitData extends AbstractMethodData {
+    static final int BIT_DATA_SIZE = cellIndexToOffset(0);
+    static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
 
-        private static final int BIT_DATA_SIZE = cellIndexToOffset(0);
-        private static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
+    static class BitData extends HotSpotMethodDataAccessor {
 
-        private BitData() {
-            super(Tag.BitData, BIT_DATA_SIZE);
+        private BitData(HotSpotVMConfig config, int tag) {
+            super(config, tag, BIT_DATA_SIZE);
         }
 
-        protected BitData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected BitData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -408,17 +296,17 @@
         }
     }
 
-    private static class CounterData extends BitData {
+    static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
+    static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
 
-        private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
-        private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
+    static class CounterData extends BitData {
 
-        CounterData() {
-            super(Tag.CounterData, COUNTER_DATA_SIZE);
+        CounterData(HotSpotVMConfig config, int tag) {
+            super(config, tag, COUNTER_DATA_SIZE);
         }
 
-        protected CounterData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected CounterData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -436,18 +324,18 @@
         }
     }
 
-    private static class JumpData extends AbstractMethodData {
+    static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
+    static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
+    static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
 
-        private static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
-        protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
-        protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
+    static class JumpData extends HotSpotMethodDataAccessor {
 
-        JumpData() {
-            super(Tag.JumpData, JUMP_DATA_SIZE);
+        JumpData(HotSpotVMConfig config, int tag) {
+            super(config, tag, JUMP_DATA_SIZE);
         }
 
-        protected JumpData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected JumpData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -484,16 +372,16 @@
         }
     }
 
-    private abstract static class AbstractTypeData extends CounterData {
+    static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
 
-        protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
+    static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
+    static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
+    static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset);
 
-        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);
+    abstract static class AbstractTypeData extends CounterData {
 
-        protected AbstractTypeData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected AbstractTypeData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -539,7 +427,7 @@
 
         protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
 
-        private static JavaTypeProfile createTypeProfile(TriState nullSeen, RawItemProfile<ResolvedJavaType> profile) {
+        private JavaTypeProfile createTypeProfile(TriState nullSeen, RawItemProfile<ResolvedJavaType> profile) {
             if (profile.entries <= 0 || profile.totalCount <= 0) {
                 return null;
             }
@@ -583,16 +471,16 @@
         }
     }
 
-    private static class ReceiverTypeData extends AbstractTypeData {
+    static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
-        private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+    static class ReceiverTypeData extends AbstractTypeData {
 
-        ReceiverTypeData() {
-            super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE);
+        ReceiverTypeData(HotSpotVMConfig config, int tag) {
+            super(config, tag, TYPE_CHECK_DATA_SIZE);
         }
 
-        protected ReceiverTypeData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected ReceiverTypeData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -606,18 +494,18 @@
         }
     }
 
-    private static class VirtualCallData extends ReceiverTypeData {
+    static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
+    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
-        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;
-        private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+    static class VirtualCallData extends ReceiverTypeData {
 
-        VirtualCallData() {
-            super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE);
+        VirtualCallData(HotSpotVMConfig config, int tag) {
+            super(config, tag, VIRTUAL_CALL_DATA_SIZE);
         }
 
-        protected VirtualCallData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected VirtualCallData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -647,7 +535,7 @@
             return createMethodProfile(getRawMethodProfile(data, position));
         }
 
-        private static RawItemProfile<ResolvedJavaMethod> getRawMethodProfile(HotSpotMethodData data, int position) {
+        private RawItemProfile<ResolvedJavaMethod> getRawMethodProfile(HotSpotMethodData data, int position) {
             int profileWidth = config.methodProfileWidth;
 
             ResolvedJavaMethod[] methods = new ResolvedJavaMethod[profileWidth];
@@ -671,7 +559,7 @@
             return new RawItemProfile<>(entries, methods, counts, totalCount);
         }
 
-        private static JavaMethodProfile createMethodProfile(RawItemProfile<ResolvedJavaMethod> profile) {
+        private JavaMethodProfile createMethodProfile(RawItemProfile<ResolvedJavaMethod> profile) {
             if (profile.entries <= 0 || profile.totalCount <= 0) {
                 return null;
             }
@@ -712,10 +600,10 @@
         }
     }
 
-    private static class VirtualCallTypeData extends VirtualCallData {
+    static class VirtualCallTypeData extends VirtualCallData {
 
-        VirtualCallTypeData() {
-            super(Tag.VirtualCallTypeData, 0);
+        VirtualCallTypeData(HotSpotVMConfig config, int tag) {
+            super(config, tag, 0);
         }
 
         @Override
@@ -725,23 +613,23 @@
         }
     }
 
-    private static class RetData extends CounterData {
+    static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
+    static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
 
-        private static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
-        private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
+    static class RetData extends CounterData {
 
-        RetData() {
-            super(Tag.RetData, RET_DATA_SIZE);
+        RetData(HotSpotVMConfig config, int tag) {
+            super(config, tag, RET_DATA_SIZE);
         }
     }
 
-    private static class BranchData extends JumpData {
+    static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
+    static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
 
-        private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
-        private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
+    static class BranchData extends JumpData {
 
-        BranchData() {
-            super(Tag.BranchData, BRANCH_DATA_SIZE);
+        BranchData(HotSpotVMConfig config, int tag) {
+            super(config, tag, BRANCH_DATA_SIZE);
         }
 
         @Override
@@ -768,13 +656,13 @@
         }
     }
 
-    private static class ArrayData extends AbstractMethodData {
+    static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
+    static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
 
-        private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
-        protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
+    static class ArrayData extends HotSpotMethodDataAccessor {
 
-        ArrayData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        ArrayData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -792,16 +680,16 @@
         }
     }
 
-    private static class MultiBranchData extends ArrayData {
+    static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
+    static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount;
+    static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
+    static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
+    static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
 
-        private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
-        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);
+    static class MultiBranchData extends ArrayData {
 
-        MultiBranchData() {
-            super(Tag.MultiBranchData, MULTI_BRANCH_DATA_SIZE);
+        MultiBranchData(HotSpotVMConfig config, int tag) {
+            super(config, tag, MULTI_BRANCH_DATA_SIZE);
         }
 
         @Override
@@ -878,18 +766,18 @@
         }
     }
 
-    private static class ArgInfoData extends ArrayData {
+    static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
 
-        private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
+    static class ArgInfoData extends ArrayData {
 
-        ArgInfoData() {
-            super(Tag.ArgInfoData, ARG_INFO_DATA_SIZE);
+        ArgInfoData(HotSpotVMConfig config, int tag) {
+            super(config, tag, ARG_INFO_DATA_SIZE);
         }
     }
 
-    private static class UnknownProfileData extends AbstractMethodData {
-        UnknownProfileData(Tag tag) {
-            super(tag, 0);
+    static class UnknownProfileData extends HotSpotMethodDataAccessor {
+        UnknownProfileData(HotSpotVMConfig config, int tag) {
+            super(config, tag, 0);
         }
 
         @Override
@@ -900,7 +788,6 @@
 
         @Override
         public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
-            // TODO Auto-generated method stub
             return null;
         }
     }
@@ -912,4 +799,41 @@
     public int getCompiledIRSize() {
         return UNSAFE.getInt(metaspaceMethodData + config.methodDataIRSizeOffset);
     }
+
+    // sorted by tag
+    // @formatter:off
+    static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
+        null,
+        new BitData(config, config.dataLayoutBitDataTag),
+        new CounterData(config, config.dataLayoutCounterDataTag),
+        new JumpData(config, config.dataLayoutJumpDataTag),
+        new ReceiverTypeData(config, config.dataLayoutReceiverTypeDataTag),
+        new VirtualCallData(config, config.dataLayoutVirtualCallDataTag),
+        new RetData(config, config.dataLayoutRetDataTag),
+        new BranchData(config, config.dataLayoutBranchDataTag),
+        new MultiBranchData(config, config.dataLayoutMultiBranchDataTag),
+        new ArgInfoData(config, config.dataLayoutArgInfoDataTag),
+        new UnknownProfileData(config, config.dataLayoutCallTypeDataTag),
+        new VirtualCallTypeData(config, config.dataLayoutVirtualCallTypeDataTag),
+        new UnknownProfileData(config, config.dataLayoutParametersTypeDataTag),
+        new UnknownProfileData(config, config.dataLayoutSpeculativeTrapDataTag),
+    };
+
+    private static boolean checkAccessorTags() {
+        int expectedTag = 0;
+        for (HotSpotMethodDataAccessor accessor : PROFILE_DATA_ACCESSORS) {
+            if (expectedTag ==0 ) {
+                assert accessor == null;
+            } else {
+                assert accessor.tag == expectedTag: expectedTag + " != " + accessor.tag + " " + accessor;
+            }
+            expectedTag++;
+        }
+        return true;
+    }
+
+    static {
+        assert checkAccessorTags();
+    }
+    // @formatter:on
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Fri Jul 01 16:50:34 2016 -0700
@@ -1,110 +1,129 @@
-/*
- * 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 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
- * data in a HotSpot methodDataOop. This interface is similar to the interface {@link ProfilingInfo}
- * , but most methods require a MethodDataObject and the exact position within the methodData.
+ * Base class for accessing the different kinds of data in a HotSpot {@code MethodData}. This is
+ * similar to {@link ProfilingInfo}, but most methods require a {@link HotSpotMethodData} and the
+ * exact position within the method data.
  */
-public interface HotSpotMethodDataAccessor {
+abstract class HotSpotMethodDataAccessor {
 
-    /**
-     * {@code DataLayout} tag values.
-     */
-    enum Tag {
-        No(config().dataLayoutNoTag),
-        BitData(config().dataLayoutBitDataTag),
-        CounterData(config().dataLayoutCounterDataTag),
-        JumpData(config().dataLayoutJumpDataTag),
-        ReceiverTypeData(config().dataLayoutReceiverTypeDataTag),
-        VirtualCallData(config().dataLayoutVirtualCallDataTag),
-        RetData(config().dataLayoutRetDataTag),
-        BranchData(config().dataLayoutBranchDataTag),
-        MultiBranchData(config().dataLayoutMultiBranchDataTag),
-        ArgInfoData(config().dataLayoutArgInfoDataTag),
-        CallTypeData(config().dataLayoutCallTypeDataTag),
-        VirtualCallTypeData(config().dataLayoutVirtualCallTypeDataTag),
-        ParametersTypeData(config().dataLayoutParametersTypeDataTag),
-        SpeculativeTrapData(config().dataLayoutSpeculativeTrapDataTag);
+    final int tag;
+    final int staticSize;
+    final HotSpotVMConfig config;
 
-        private final int value;
-
-        Tag(int value) {
-            this.value = value;
-        }
-
-        public int getValue() {
-            return value;
-        }
-
-        public static Tag getEnum(int value) {
-            Tag result = values()[value];
-            assert value == result.value;
-            return result;
-        }
+    protected HotSpotMethodDataAccessor(HotSpotVMConfig config, int tag, int staticSize) {
+        this.config = config;
+        this.tag = tag;
+        this.staticSize = staticSize;
     }
 
     /**
-     * Returns the {@link Tag} stored in the LayoutData header.
+     * Returns the tag stored in the LayoutData header.
      *
      * @return tag stored in the LayoutData header
      */
-    Tag getTag();
+    int getTag() {
+        return tag;
+    }
+
+    static int readTag(HotSpotVMConfig config, HotSpotMethodData data, int position) {
+        final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
+        assert tag >= config.dataLayoutNoTag && tag <= config.dataLayoutSpeculativeTrapDataTag : "profile data tag out of bounds: " + tag;
+        return tag;
+    }
 
     /**
      * Returns the BCI stored in the LayoutData header.
      *
-     * @return An integer &ge; 0 and &le; Short.MAX_VALUE, or -1 if not supported.
+     * @return an integer between 0 and {@link Short#MAX_VALUE} inclusive, or -1 if not supported
      */
-    int getBCI(HotSpotMethodData data, int position);
+    int getBCI(HotSpotMethodData data, int position) {
+        return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
+    }
 
     /**
      * Computes the size for the specific data at the given position.
      *
-     * @return An integer &gt; 0.
+     * @return a value greater than 0
      */
-    int getSize(HotSpotMethodData data, int position);
+    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;
+    }
 
-    JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position);
+    TriState getExceptionSeen(HotSpotMethodData data, int position) {
+        final int EXCEPTIONS_MASK = 1 << config.bitDataExceptionSeenFlag;
+        return TriState.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0);
+    }
 
-    JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
+        return null;
+    }
 
-    double getBranchTakenProbability(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
+        return null;
+    }
 
-    double[] getSwitchProbabilities(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    double getBranchTakenProbability(HotSpotMethodData data, int position) {
+        return -1;
+    }
 
-    TriState getExceptionSeen(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
+        return null;
+    }
 
-    TriState getNullSeen(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    int getExecutionCount(HotSpotMethodData data, int position) {
+        return -1;
+    }
 
-    int getExecutionCount(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    TriState getNullSeen(HotSpotMethodData data, int position) {
+        return TriState.UNKNOWN;
+    }
 
-    StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
-}
+    protected int getFlags(HotSpotMethodData data, int position) {
+        return data.readUnsignedByte(position, config.dataLayoutFlagsOffset);
+    }
+
+    /**
+     * @param data
+     * @param position
+     */
+    protected int getDynamicSize(HotSpotMethodData data, int position) {
+        return 0;
+    }
+
+    abstract StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
+
+}
\ No newline at end of file
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java	Fri Jul 01 16:50:34 2016 -0700
@@ -27,13 +27,25 @@
 import jdk.vm.ci.code.Location;
 import jdk.vm.ci.code.ReferenceMap;
 
+/**
+ * Describes where the object references are in machine state, compliant with what HotSpot expects.
+ */
 public final class HotSpotReferenceMap extends ReferenceMap {
 
-    final Location[] objects;
-    final Location[] derivedBase;
-    final int[] sizeInBytes;
-    final int maxRegisterSize;
+    private final Location[] objects;
+    private final Location[] derivedBase;
+    private final int[] sizeInBytes;
+    private final int maxRegisterSize;
 
+    /**
+     *
+     * @param objects This array is now owned by this object and must not be mutated by the caller.
+     * @param derivedBase This array is now owned by this object and must not be mutated by the
+     *            caller.
+     * @param sizeInBytes This array is now owned by this object and must not be mutated by the
+     *            caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `objects`, `derivedBase` and `sizeInBytes`")
     public HotSpotReferenceMap(Location[] objects, Location[] derivedBase, int[] sizeInBytes, int maxRegisterSize) {
         this.objects = objects;
         this.derivedBase = derivedBase;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Fri Jul 01 16:50:34 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,12 +28,8 @@
 import java.lang.reflect.Field;
 
 import jdk.internal.vm.annotation.Stable;
-import jdk.vm.ci.common.JVMCIError;
-import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
 import jdk.vm.ci.meta.JavaType;
-import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ModifiersProvider;
-import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri Jul 01 16:50:34 2016 -0700
@@ -132,10 +132,20 @@
         return UNSAFE.getInt(javaClass, config().klassOffset) & 0xFFFFFFFFL;
     }
 
+    @Override
     public long getMetaspacePointer() {
         return getMetaspaceKlass();
     }
 
+    /**
+     * The Klass* for this object is kept alive by the direct reference to {@link #javaClass} so no
+     * extra work is required.
+     */
+    @Override
+    public boolean isRegistered() {
+        return true;
+    }
+
     @Override
     public int getModifiers() {
         if (isArray()) {
@@ -428,7 +438,13 @@
     }
 
     public HotSpotConstantPool getConstantPool() {
-        if (constantPool == null) {
+        if (constantPool == null || !isArray() && UNSAFE.getAddress(getMetaspaceKlass() + config().instanceKlassConstantsOffset) != constantPool.getMetaspaceConstantPool()) {
+            /*
+             * If the pointer to the ConstantPool has changed since this was last read refresh the
+             * HotSpotConstantPool wrapper object. This ensures that uses of the constant pool are
+             * operating on the latest one and that HotSpotResolvedJavaMethodImpls will be able to
+             * use the shared copy instead of creating their own instance.
+             */
             constantPool = compilerToVM().getConstantPool(this, config().instanceKlassConstantsOffset);
         }
         return constantPool;
@@ -575,7 +591,8 @@
             // Get Klass::_fields
             final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
             assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";
-            metaspaceData = metaspaceFields + config.arrayU2DataOffset + config.fieldInfoFieldSlots * Short.BYTES * index;
+            int offset = config.fieldInfoFieldSlots * Short.BYTES * index;
+            metaspaceData = metaspaceFields + config.arrayU2DataOffset + offset;
         }
 
         private int getAccessFlags() {
@@ -603,7 +620,8 @@
          * on top an array of Java shorts.
          */
         private int readFieldSlot(int index) {
-            return UNSAFE.getChar(metaspaceData + Short.BYTES * index);
+            int offset = Short.BYTES * index;
+            return UNSAFE.getChar(metaspaceData + offset);
         }
 
         /**
@@ -612,7 +630,7 @@
          */
         public String getName() {
             final int nameIndex = getNameIndex();
-            return isInternal() ? HotSpotVmSymbols.symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
+            return isInternal() ? config().symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
         }
 
         /**
@@ -621,7 +639,7 @@
          */
         public String getSignature() {
             final int signatureIndex = getSignatureIndex();
-            return isInternal() ? HotSpotVmSymbols.symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
+            return isInternal() ? config().symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
         }
 
         public JavaType getType() {
@@ -642,6 +660,7 @@
         }
     }
 
+    @SuppressFBWarnings(value = "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE", justification = "comparator is only used transiently")
     private static class OffsetComparator implements java.util.Comparator<HotSpotResolvedJavaField> {
         @Override
         public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Fri Jul 01 16:50:34 2016 -0700
@@ -35,7 +35,7 @@
     /** Written by the C++ code that performs deoptimization. */
     private volatile Object lastFailed;
 
-    /** All speculations that have been a deoptimization reason. */
+    /** All speculations that have caused a deoptimization. */
     private Set<SpeculationReason> failedSpeculations;
 
     /** Strong references to all reasons embedded in the current nmethod. */
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public boolean maySpeculate(SpeculationReason reason) {
+    public synchronized boolean maySpeculate(SpeculationReason reason) {
         if (failedSpeculations != null && failedSpeculations.contains(reason)) {
             return false;
         }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Wed Jul 05 21:55:11 2017 +0200
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri Jul 01 16:50:34 2016 -0700
@@ -25,1639 +25,310 @@
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.HashMap;
-import java.util.Iterator;
-
 import jdk.internal.misc.Unsafe;
-import jdk.internal.vm.annotation.Stable;
-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.HotSpotVMType;
 
 /**
  * Used to access native configuration details.
  *
  * All non-static, public fields in this class are so that they can be compiled as constants.
  */
-public class HotSpotVMConfig {
+class HotSpotVMConfig extends HotSpotVMConfigAccess {
 
     /**
      * Gets the configuration associated with the singleton {@link HotSpotJVMCIRuntime}.
      */
-    public static HotSpotVMConfig config() {
+    static HotSpotVMConfig config() {
         return runtime().getConfig();
     }
 
-    /**
-     * Maximum allowed size of allocated area for a frame.
-     */
-    public final int maxFrameSize = 16 * 1024;
+    private final String osArch = getHostArchitectureName();
 
-    public HotSpotVMConfig(CompilerToVM compilerToVm) {
-        // Get raw pointer to the array that contains all gHotSpotVM values.
-        final long gHotSpotVMData = compilerToVm.initializeConfiguration(this);
-        assert gHotSpotVMData != 0;
-
-        // Make FindBugs happy.
-        jvmciHotSpotVMStructs = 0;
-        jvmciHotSpotVMTypes = 0;
-        jvmciHotSpotVMIntConstants = 0;
-        jvmciHotSpotVMLongConstants = 0;
-        jvmciHotSpotVMAddresses = 0;
-
-        // Initialize the gHotSpotVM fields.
-        for (Field f : HotSpotVMConfig.class.getDeclaredFields()) {
-            if (f.isAnnotationPresent(HotSpotVMData.class)) {
-                HotSpotVMData annotation = f.getAnnotation(HotSpotVMData.class);
-                final int index = annotation.index();
-                final long value = UNSAFE.getAddress(gHotSpotVMData + Unsafe.ADDRESS_SIZE * index);
-                try {
-                    f.setLong(this, value);
-                } catch (IllegalAccessException e) {
-                    throw new JVMCIError("index " + index, e);
-                }
-            }
-        }
-
-        // Quick sanity check.
-        assert jvmciHotSpotVMStructs != 0;
-        assert jvmciHotSpotVMTypes != 0;
-        assert jvmciHotSpotVMIntConstants != 0;
-        assert jvmciHotSpotVMLongConstants != 0;
-        assert jvmciHotSpotVMAddresses != 0;
-
-        initialize();
-
-        oopEncoding = new CompressEncoding(narrowOopBase, narrowOopShift, logMinObjAlignment());
-        klassEncoding = new CompressEncoding(narrowKlassBase, narrowKlassShift, logKlassAlignment);
-
-        assert check();
-        assert HotSpotVMConfigVerifier.check();
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getSimpleName();
-    }
-
-    /**
-     * Reads a {@code '\0'} terminated C string from native memory and converts it to a
-     * {@link String}.
-     *
-     * @return a Java string
-     */
-    private static String readCString(Unsafe unsafe, long address) {
-        if (address == 0) {
-            return null;
-        }
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0;; i++) {
-            char c = (char) unsafe.getByte(address + i);
-            if (c == 0) {
-                break;
-            }
-            sb.append(c);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Initialize fields by reading their values from vmStructs.
-     */
-    private void initialize() {
-        // Fill the VM fields hash map.
-        HashMap<String, VMFields.Field> vmFields = new HashMap<>();
-        for (VMFields.Field e : new VMFields(jvmciHotSpotVMStructs)) {
-            vmFields.put(e.getName(), e);
-        }
-
-        // Fill the VM types hash map.
-        HashMap<String, VMTypes.Type> vmTypes = new HashMap<>();
-        for (VMTypes.Type e : new VMTypes(jvmciHotSpotVMTypes)) {
-            vmTypes.put(e.getTypeName(), e);
-        }
-
-        // Fill the VM constants hash map.
-        HashMap<String, AbstractConstant> vmConstants = new HashMap<>();
-        for (AbstractConstant e : new VMIntConstants(jvmciHotSpotVMIntConstants)) {
-            vmConstants.put(e.getName(), e);
-        }
-        for (AbstractConstant e : new VMLongConstants(jvmciHotSpotVMLongConstants)) {
-            vmConstants.put(e.getName(), e);
-        }
-
-        // Fill the VM addresses hash map.
-        HashMap<String, VMAddresses.Address> vmAddresses = new HashMap<>();
-        for (VMAddresses.Address e : new VMAddresses(jvmciHotSpotVMAddresses)) {
-            vmAddresses.put(e.getName(), e);
-        }
-
-        // Fill the flags hash map.
-        HashMap<String, Flags.Flag> flags = new HashMap<>();
-        for (Flags.Flag e : new Flags(vmFields, vmTypes)) {
-            flags.put(e.getName(), e);
-        }
-
-        String osName = getHostOSName();
-        String osArch = getHostArchitectureName();
-
-        for (Field f : HotSpotVMConfig.class.getDeclaredFields()) {
-            if (f.isAnnotationPresent(HotSpotVMField.class)) {
-                HotSpotVMField annotation = f.getAnnotation(HotSpotVMField.class);
-                String name = annotation.name();
-                String type = annotation.type();
-                VMFields.Field entry = vmFields.get(name);
-                if (entry == null) {
-                    if (!isRequired(osArch, annotation.archs())) {
-                        continue;
-                    }
-                    throw new JVMCIError(f.getName() + ": expected VM field not found: " + name);
-                }
-
-                // Make sure the native type is still the type we expect.
-                if (!type.isEmpty()) {
-                    if (!type.equals(entry.getTypeString())) {
-                        throw new JVMCIError(f.getName() + ": compiler expects type " + type + " but VM field " + name + " is of type " + entry.getTypeString());
-                    }
-                }
-
-                switch (annotation.get()) {
-                    case OFFSET:
-                        setField(f, entry.getOffset());
-                        break;
-                    case ADDRESS:
-                        setField(f, entry.getAddress());
-                        break;
-                    case VALUE:
-                        setField(f, entry.getValue());
-                        break;
-                    default:
-                        throw new JVMCIError(f.getName() + ": unknown kind: " + annotation.get());
-                }
-            } else if (f.isAnnotationPresent(HotSpotVMType.class)) {
-                HotSpotVMType annotation = f.getAnnotation(HotSpotVMType.class);
-                String name = annotation.name();
-                VMTypes.Type entry = vmTypes.get(name);
-                if (entry == null) {
-                    throw new JVMCIError(f.getName() + ": expected VM type not found: " + name);
-                }
-
-                switch (annotation.get()) {
-                    case SIZE:
-                        setField(f, entry.getSize());
-                        break;
-                    default:
-                        throw new JVMCIError(f.getName() + ": unknown kind: " + annotation.get());
-                }
-            } else if (f.isAnnotationPresent(HotSpotVMConstant.class)) {
-                HotSpotVMConstant annotation = f.getAnnotation(HotSpotVMConstant.class);
-                String name = annotation.name();
-                AbstractConstant entry = vmConstants.get(name);
-                if (entry == null) {
-                    if (!isRequired(osArch, annotation.archs())) {
-                        continue;
-                    }
-                    throw new JVMCIError(f.getName() + ": expected VM constant not found: " + name);
-                }
-                setField(f, entry.getValue());
-            } else if (f.isAnnotationPresent(HotSpotVMAddress.class)) {
-                HotSpotVMAddress annotation = f.getAnnotation(HotSpotVMAddress.class);
-                String name = annotation.name();
-                VMAddresses.Address entry = vmAddresses.get(name);
-                if (entry == null) {
-                    if (!isRequired(osName, annotation.os())) {
-                        continue;
-                    }
-                    throw new JVMCIError(f.getName() + ": expected VM address not found: " + name);
-                }
-                setField(f, entry.getValue());
-            } else if (f.isAnnotationPresent(HotSpotVMFlag.class)) {
-                HotSpotVMFlag annotation = f.getAnnotation(HotSpotVMFlag.class);
-                String name = annotation.name();
-                Flags.Flag entry = flags.get(name);
-                if (entry == null) {
-                    if (annotation.optional() || !isRequired(osArch, annotation.archs())) {
-                        continue;
-                    }
-                    throw new JVMCIError(f.getName() + ": expected VM flag not found: " + name);
-
-                }
-                setField(f, entry.getValue());
-            }
-        }
-    }
-
-    private final CompressEncoding oopEncoding;
-    private final CompressEncoding klassEncoding;
-
-    public CompressEncoding getOopEncoding() {
-        return oopEncoding;
-    }
-
-    public CompressEncoding getKlassEncoding() {
-        return klassEncoding;
-    }
-
-    private void setField(Field field, Object value) {
-        try {
-            Class<?> fieldType = field.getType();
-            if (fieldType == boolean.class) {
-                if (value instanceof String) {
-                    field.setBoolean(this, Boolean.valueOf((String) value));
-                } else if (value instanceof Boolean) {
-                    field.setBoolean(this, (boolean) value);
-                } else if (value instanceof Long) {
-                    field.setBoolean(this, ((long) value) != 0);
-                } else {
-                    throw new JVMCIError(value.getClass().getSimpleName());
-                }
-            } else if (fieldType == byte.class) {
-                if (value instanceof Long) {
-                    field.setByte(this, (byte) (long) value);
-                } else {
-                    throw new JVMCIError(value.getClass().getSimpleName());
-                }
-            } else if (fieldType == int.class) {
-                if (value instanceof Integer) {
-                    field.setInt(this, (int) value);
-                } else if (value instanceof Long) {
-                    field.setInt(this, (int) (long) value);
-                } else {
-                    throw new JVMCIError(value.getClass().getSimpleName());
-                }
-            } else if (fieldType == long.class) {
-                field.setLong(this, (long) value);
-            } else {
-                throw new JVMCIError(field.toString());
-            }
-        } catch (IllegalAccessException e) {
-            throw new JVMCIError("%s: %s", field, e);
-        }
-    }
-
-    /**
-     * Gets the host operating system name.
-     */
-    private static String getHostOSName() {
-        String osName = System.getProperty("os.name");
-        switch (osName) {
-            case "Linux":
-                osName = "linux";
-                break;
-            case "SunOS":
-                osName = "solaris";
-                break;
-            case "Mac OS X":
-                osName = "bsd";
-                break;
-            default:
-                // Of course Windows is different...
-                if (osName.startsWith("Windows")) {
-                    osName = "windows";
-                } else {
-                    throw new JVMCIError("Unexpected OS name: " + osName);
-                }
-        }
-        return osName;
+    HotSpotVMConfig(HotSpotVMConfigStore store) {
+        super(store);
     }
 
     /**
      * Gets the host architecture name for the purpose of finding the corresponding
      * {@linkplain HotSpotJVMCIBackendFactory backend}.
      */
-    public String getHostArchitectureName() {
+    String getHostArchitectureName() {
         String arch = System.getProperty("os.arch");
         switch (arch) {
             case "x86_64":
-                arch = "amd64";
-                break;
+                return "amd64";
+
             case "sparcv9":
-                arch = "sparc";
-                break;
-        }
-        return arch;
-    }
-
-    /**
-     * Determines if the current specification is included in a given set of specifications.
-     *
-     * @param current
-     * @param specification specifies a set of specifications, e.g. architectures or operating
-     *            systems. A zero length value implies all.
-     */
-    private static boolean isRequired(String current, String[] specification) {
-        if (specification.length == 0) {
-            return true;
-        }
-        for (String arch : specification) {
-            if (arch.equals(current)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * VMStructEntry (see {@code vmStructs.hpp}).
-     */
-    @HotSpotVMData(index = 0) @Stable private long jvmciHotSpotVMStructs;
-    @HotSpotVMData(index = 1) @Stable private long jvmciHotSpotVMStructEntryTypeNameOffset;
-    @HotSpotVMData(index = 2) @Stable private long jvmciHotSpotVMStructEntryFieldNameOffset;
-    @HotSpotVMData(index = 3) @Stable private long jvmciHotSpotVMStructEntryTypeStringOffset;
-    @HotSpotVMData(index = 4) @Stable private long jvmciHotSpotVMStructEntryIsStaticOffset;
-    @HotSpotVMData(index = 5) @Stable private long jvmciHotSpotVMStructEntryOffsetOffset;
-    @HotSpotVMData(index = 6) @Stable private long jvmciHotSpotVMStructEntryAddressOffset;
-    @HotSpotVMData(index = 7) @Stable private long jvmciHotSpotVMStructEntryArrayStride;
-
-    final class VMFields implements Iterable<VMFields.Field> {
-
-        private final long address;
-
-        VMFields(long address) {
-            this.address = address;
-        }
-
-        public Iterator<VMFields.Field> iterator() {
-            return new Iterator<VMFields.Field>() {
-
-                private int index = 0;
-
-                private Field current() {
-                    return new Field(address + jvmciHotSpotVMStructEntryArrayStride * index);
-                }
-
-                /**
-                 * The last entry is identified by a NULL fieldName.
-                 */
-                public boolean hasNext() {
-                    Field entry = current();
-                    return entry.getFieldName() != null;
-                }
-
-                public Field next() {
-                    Field entry = current();
-                    index++;
-                    return entry;
-                }
-            };
-        }
-
-        final class Field {
-
-            private final long entryAddress;
-
-            Field(long address) {
-                this.entryAddress = address;
-            }
-
-            public String getTypeName() {
-                long typeNameAddress = UNSAFE.getAddress(entryAddress + jvmciHotSpotVMStructEntryTypeNameOffset);
-                return readCString(UNSAFE, typeNameAddress);
-            }
-
-            public String getFieldName() {
-                long fieldNameAddress = UNSAFE.getAddress(entryAddress + jvmciHotSpotVMStructEntryFieldNameOffset);
-                return readCString(UNSAFE, fieldNameAddress);
-            }
-
-            public String getTypeString() {
-                long typeStringAddress = UNSAFE.getAddress(entryAddress + jvmciHotSpotVMStructEntryTypeStringOffset);
-                return readCString(UNSAFE, typeStringAddress);
-            }
-
-            public boolean isStatic() {
-                return UNSAFE.getInt(entryAddress + jvmciHotSpotVMStructEntryIsStaticOffset) != 0;
-            }
-
-            public long getOffset() {
-                return UNSAFE.getLong(entryAddress + jvmciHotSpotVMStructEntryOffsetOffset);
-            }
-
-            public long getAddress() {
-                return UNSAFE.getAddress(entryAddress + jvmciHotSpotVMStructEntryAddressOffset);
-            }
-
-            public String getName() {
-                String typeName = getTypeName();
-                String fieldName = getFieldName();
-                return typeName + "::" + fieldName;
-            }
-
-            public long getValue() {
-                String type = getTypeString();
-                switch (type) {
-                    case "bool":
-                        return UNSAFE.getByte(getAddress());
-                    case "int":
-                        return UNSAFE.getInt(getAddress());
-                    case "uint64_t":
-                        return UNSAFE.getLong(getAddress());
-                    case "address":
-                    case "intptr_t":
-                    case "uintptr_t":
-                    case "size_t":
-                        return UNSAFE.getAddress(getAddress());
-                    default:
-                        // All foo* types are addresses.
-                        if (type.endsWith("*")) {
-                            return UNSAFE.getAddress(getAddress());
-                        }
-                        throw new JVMCIError(type);
-                }
-            }
-
-            @Override
-            public String toString() {
-                return String.format("Field[typeName=%s, fieldName=%s, typeString=%s, isStatic=%b, offset=%d, address=0x%x]", getTypeName(), getFieldName(), getTypeString(), isStatic(), getOffset(),
-                                getAddress());
-            }
+                return "sparc";
+            default:
+                return arch;
         }
     }
 
-    /**
-     * VMTypeEntry (see vmStructs.hpp).
-     */
-    @HotSpotVMData(index = 8) @Stable private long jvmciHotSpotVMTypes;
-    @HotSpotVMData(index = 9) @Stable private long jvmciHotSpotVMTypeEntryTypeNameOffset;
-    @HotSpotVMData(index = 10) @Stable private long jvmciHotSpotVMTypeEntrySuperclassNameOffset;
-    @HotSpotVMData(index = 11) @Stable private long jvmciHotSpotVMTypeEntryIsOopTypeOffset;
-    @HotSpotVMData(index = 12) @Stable private long jvmciHotSpotVMTypeEntryIsIntegerTypeOffset;
-    @HotSpotVMData(index = 13) @Stable private long jvmciHotSpotVMTypeEntryIsUnsignedOffset;
-    @HotSpotVMData(index = 14) @Stable private long jvmciHotSpotVMTypeEntrySizeOffset;
-    @HotSpotVMData(index = 15) @Stable private long jvmciHotSpotVMTypeEntryArrayStride;
+    final boolean useDeferredInitBarriers = getFlag("ReduceInitialCardMarks", Boolean.class);
 
-    final class VMTypes implements Iterable<VMTypes.Type> {
+    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
 
-        private final long address;
-
-        VMTypes(long address) {
-            this.address = address;
-        }
-
-        public Iterator<VMTypes.Type> iterator() {
-            return new Iterator<VMTypes.Type>() {
-
-                private int index = 0;
-
-                private Type current() {
-                    return new Type(address + jvmciHotSpotVMTypeEntryArrayStride * index);
-                }
-
-                /**
-                 * The last entry is identified by a NULL type name.
-                 */
-                public boolean hasNext() {
-                    Type entry = current();
-                    return entry.getTypeName() != null;
-                }
-
-                public Type next() {
-                    Type entry = current();
-                    index++;
-                    return entry;
-                }
-            };
-        }
-
-        final class Type {
-
-            private final long entryAddress;
-
-            Type(long address) {
-                this.entryAddress = address;
-            }
-
-            public String getTypeName() {
-                long typeNameAddress = UNSAFE.getAddress(entryAddress + jvmciHotSpotVMTypeEntryTypeNameOffset);
-                return readCString(UNSAFE, typeNameAddress);
-            }
-
-            public String getSuperclassName() {
-                long superclassNameAddress = UNSAFE.getAddress(entryAddress + jvmciHotSpotVMTypeEntrySuperclassNameOffset);
-                return readCString(UNSAFE, superclassNameAddress);
-            }
-
-            public boolean isOopType() {
-                return UNSAFE.getInt(entryAddress + jvmciHotSpotVMTypeEntryIsOopTypeOffset) != 0;
-            }
-
-            public boolean isIntegerType() {
-                return UNSAFE.getInt(entryAddress + jvmciHotSpotVMTypeEntryIsIntegerTypeOffset) != 0;
-            }
-
-            public boolean isUnsigned() {
-                return UNSAFE.getInt(entryAddress + jvmciHotSpotVMTypeEntryIsUnsignedOffset) != 0;
-            }
-
-            public long getSize() {
-                return UNSAFE.getLong(entryAddress + jvmciHotSpotVMTypeEntrySizeOffset);
-            }
-
-            @Override
-            public String toString() {
-                return String.format("Type[typeName=%s, superclassName=%s, isOopType=%b, isIntegerType=%b, isUnsigned=%b, size=%d]", getTypeName(), getSuperclassName(), isOopType(), isIntegerType(),
-                                isUnsigned(), getSize());
-            }
-        }
-    }
-
-    public abstract class AbstractConstant {
-
-        protected final long address;
-        protected final long nameOffset;
-        protected final long valueOffset;
-
-        AbstractConstant(long address, long nameOffset, long valueOffset) {
-            this.address = address;
-            this.nameOffset = nameOffset;
-            this.valueOffset = valueOffset;
-        }
-
-        public String getName() {
-            long nameAddress = UNSAFE.getAddress(address + nameOffset);
-            return readCString(UNSAFE, nameAddress);
-        }
-
-        public abstract long getValue();
-    }
-
-    /**
-     * VMIntConstantEntry (see vmStructs.hpp).
-     */
-    @HotSpotVMData(index = 16) @Stable private long jvmciHotSpotVMIntConstants;
-    @HotSpotVMData(index = 17) @Stable private long jvmciHotSpotVMIntConstantEntryNameOffset;
-    @HotSpotVMData(index = 18) @Stable private long jvmciHotSpotVMIntConstantEntryValueOffset;
-    @HotSpotVMData(index = 19) @Stable private long jvmciHotSpotVMIntConstantEntryArrayStride;
-
-    final class VMIntConstants implements Iterable<VMIntConstants.Constant> {
-
-        private final long address;
-
-        VMIntConstants(long address) {
-            this.address = address;
-        }
-
-        public Iterator<VMIntConstants.Constant> iterator() {
-            return new Iterator<VMIntConstants.Constant>() {
-
-                private int index = 0;
-
-                private Constant current() {
-                    return new Constant(address + jvmciHotSpotVMIntConstantEntryArrayStride * index);
-                }
-
-                /**
-                 * The last entry is identified by a NULL name.
-                 */
-                public boolean hasNext() {
-                    Constant entry = current();
-                    return entry.getName() != null;
-                }
-
-                public Constant next() {
-                    Constant entry = current();
-                    index++;
-                    return entry;
-                }
-            };
-        }
-
-        final class Constant extends AbstractConstant {
-
-            Constant(long address) {
-                super(address, jvmciHotSpotVMIntConstantEntryNameOffset, jvmciHotSpotVMIntConstantEntryValueOffset);
-            }
-
-            @Override
-            public long getValue() {
-                return UNSAFE.getInt(address + valueOffset);
-            }
-
-            @Override
-            public String toString() {
-                return String.format("IntConstant[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue());
-            }
-        }
-    }
-
-    /**
-     * VMLongConstantEntry (see vmStructs.hpp).
-     */
-    @HotSpotVMData(index = 20) @Stable private long jvmciHotSpotVMLongConstants;
-    @HotSpotVMData(index = 21) @Stable private long jvmciHotSpotVMLongConstantEntryNameOffset;
-    @HotSpotVMData(index = 22) @Stable private long jvmciHotSpotVMLongConstantEntryValueOffset;
-    @HotSpotVMData(index = 23) @Stable private long jvmciHotSpotVMLongConstantEntryArrayStride;
-
-    final class VMLongConstants implements Iterable<VMLongConstants.Constant> {
-
-        private final long address;
-
-        VMLongConstants(long address) {
-            this.address = address;
-        }
-
-        public Iterator<VMLongConstants.Constant> iterator() {
-            return new Iterator<VMLongConstants.Constant>() {
-
-                private int index = 0;
-
-                private Constant currentEntry() {
-                    return new Constant(address + jvmciHotSpotVMLongConstantEntryArrayStride * index);
-                }
-
-                /**
-                 * The last entry is identified by a NULL name.
-                 */
-                public boolean hasNext() {
-                    Constant entry = currentEntry();
-                    return entry.getName() != null;
-                }
-
-                public Constant next() {
-                    Constant entry = currentEntry();
-                    index++;
-                    return entry;
-                }
-            };
-        }
-
-        final class Constant extends AbstractConstant {
-
-            Constant(long address) {
-                super(address, jvmciHotSpotVMLongConstantEntryNameOffset, jvmciHotSpotVMLongConstantEntryValueOffset);
-            }
-
-            @Override
-            public long getValue() {
-                return UNSAFE.getLong(address + valueOffset);
-            }
-
-            @Override
-            public String toString() {
-                return String.format("LongConstant[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue());
-            }
-        }
-    }
-
-    /**
-     * VMAddressEntry (see vmStructs.hpp).
-     */
-    @HotSpotVMData(index = 24) @Stable private long jvmciHotSpotVMAddresses;
-    @HotSpotVMData(index = 25) @Stable private long jvmciHotSpotVMAddressEntryNameOffset;
-    @HotSpotVMData(index = 26) @Stable private long jvmciHotSpotVMAddressEntryValueOffset;
-    @HotSpotVMData(index = 27) @Stable private long jvmciHotSpotVMAddressEntryArrayStride;
-
-    final class VMAddresses implements Iterable<VMAddresses.Address> {
-
-        private final long address;
-
-        VMAddresses(long address) {
-            this.address = address;
-        }
-
-        public Iterator<VMAddresses.Address> iterator() {
-            return new Iterator<VMAddresses.Address>() {
-
-                private int index = 0;
-
-                private Address currentEntry() {
-                    return new Address(address + jvmciHotSpotVMAddressEntryArrayStride * index);
-                }
-
-                /**
-                 * The last entry is identified by a NULL name.
-                 */
-                public boolean hasNext() {
-                    Address entry = currentEntry();
-                    return entry.getName() != null;
-                }
-
-                public Address next() {
-                    Address entry = currentEntry();
-                    index++;
-                    return entry;
-                }
-            };
-        }
-
-        final class Address extends AbstractConstant {
-
-            Address(long address) {
-                super(address, jvmciHotSpotVMAddressEntryNameOffset, jvmciHotSpotVMAddressEntryValueOffset);
-            }
-
-            @Override
-            public long getValue() {
-                return UNSAFE.getLong(address + valueOffset);
-            }
-
-            @Override
-            public String toString() {
-                return String.format("Address[name=%s, value=%d (0x%x)]", getName(), getValue(), getValue());
-            }
-        }
-    }
-
-    final class Flags implements Iterable<Flags.Flag> {
-
-        private final long address;
-        private final long entrySize;
-        private final long typeOffset;
-        private final long nameOffset;
-        private final long addrOffset;
-
-        Flags(HashMap<String, VMFields.Field> vmStructs, HashMap<String, VMTypes.Type> vmTypes) {
-            address = vmStructs.get("Flag::flags").getValue();
-            entrySize = vmTypes.get("Flag").getSize();
-            typeOffset = vmStructs.get("Flag::_type").getOffset();
-            nameOffset = vmStructs.get("Flag::_name").getOffset();
-            addrOffset = vmStructs.get("Flag::_addr").getOffset();
-
-            assert vmTypes.get("bool").getSize() == Byte.BYTES;
-            assert vmTypes.get("intx").getSize() == Long.BYTES;
-            assert vmTypes.get("uintx").getSize() == Long.BYTES;
-        }
-
-        public Iterator<Flags.Flag> iterator() {
-            return new Iterator<Flags.Flag>() {
-
-                private int index = 0;
-
-                private Flag current() {
-                    return new Flag(address + entrySize * index);
-                }
-
-                /**
-                 * The last entry is identified by a NULL name.
-                 */
-                public boolean hasNext() {
-                    Flag entry = current();
-                    return entry.getName() != null;
-                }
-
-                public Flag next() {
-                    Flag entry = current();
-                    index++;
-                    return entry;
-                }
-            };
-        }
-
-        final class Flag {
-
-            private final long entryAddress;
-
-            Flag(long address) {
-                this.entryAddress = address;
-            }
-
-            public String getType() {
-                long typeAddress = UNSAFE.getAddress(entryAddress + typeOffset);
-                return readCString(UNSAFE, typeAddress);
-            }
-
-            public String getName() {
-                long nameAddress = UNSAFE.getAddress(entryAddress + nameOffset);
-                return readCString(UNSAFE, nameAddress);
-            }
-
-            public long getAddr() {
-                return UNSAFE.getAddress(entryAddress + addrOffset);
-            }
-
-            public Object getValue() {
-                switch (getType()) {
-                    case "bool":
-                        return Boolean.valueOf(UNSAFE.getByte(getAddr()) != 0);
-                    case "intx":
-                    case "uintx":
-                    case "uint64_t":
-                        return Long.valueOf(UNSAFE.getLong(getAddr()));
-                    case "double":
-                        return Double.valueOf(UNSAFE.getDouble(getAddr()));
-                    case "ccstr":
-                    case "ccstrlist":
-                        return readCString(UNSAFE, getAddr());
-                    default:
-                        throw new JVMCIError(getType());
-                }
-            }
-
-            @Override
-            public String toString() {
-                return String.format("Flag[type=%s, name=%s, value=%s]", getType(), getName(), getValue());
-            }
-        }
-    }
-
-    @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;
-    @HotSpotVMFlag(name = "CITime") @Stable public boolean ciTime;
-    @HotSpotVMFlag(name = "CITimeEach") @Stable public boolean ciTimeEach;
-    @HotSpotVMFlag(name = "CompileTheWorldStartAt", optional = true) @Stable public int compileTheWorldStartAt;
-    @HotSpotVMFlag(name = "CompileTheWorldStopAt", optional = true) @Stable public int compileTheWorldStopAt;
-    @HotSpotVMFlag(name = "DontCompileHugeMethods") @Stable public boolean dontCompileHugeMethods;
-    @HotSpotVMFlag(name = "HugeMethodLimit") @Stable public int hugeMethodLimit;
-    @HotSpotVMFlag(name = "PrintInlining") @Stable public boolean printInlining;
-    @HotSpotVMFlag(name = "Inline") @Stable public boolean inline;
-    @HotSpotVMFlag(name = "JVMCIUseFastLocking") @Stable public boolean useFastLocking;
-    @HotSpotVMFlag(name = "ForceUnreachable") @Stable public boolean forceUnreachable;
-    @HotSpotVMFlag(name = "CodeCacheSegmentSize") @Stable public int codeSegmentSize;
-    @HotSpotVMFlag(name = "FoldStableValues") @Stable public boolean foldStableValues;
-
-    @HotSpotVMFlag(name = "UseTLAB") @Stable public boolean useTLAB;
-    @HotSpotVMFlag(name = "UseBiasedLocking") @Stable public boolean useBiasedLocking;
-    @HotSpotVMFlag(name = "UsePopCountInstruction") @Stable public boolean usePopCountInstruction;
-    @HotSpotVMFlag(name = "UseCountLeadingZerosInstruction", archs = {"amd64"}) @Stable public boolean useCountLeadingZerosInstruction;
-    @HotSpotVMFlag(name = "UseCountTrailingZerosInstruction", archs = {"amd64"}) @Stable public boolean useCountTrailingZerosInstruction;
-    @HotSpotVMFlag(name = "UseAESIntrinsics") @Stable public boolean useAESIntrinsics;
-    @HotSpotVMFlag(name = "UseCRC32Intrinsics") @Stable public boolean useCRC32Intrinsics;
-    @HotSpotVMFlag(name = "UseG1GC") @Stable public boolean useG1GC;
-    @HotSpotVMFlag(name = "UseConcMarkSweepGC") @Stable public boolean useCMSGC;
-
-    @HotSpotVMFlag(name = "AllocatePrefetchStyle") @Stable public int allocatePrefetchStyle;
-    @HotSpotVMFlag(name = "AllocatePrefetchInstr") @Stable public int allocatePrefetchInstr;
-    @HotSpotVMFlag(name = "AllocatePrefetchLines") @Stable public int allocatePrefetchLines;
-    @HotSpotVMFlag(name = "AllocateInstancePrefetchLines") @Stable public int allocateInstancePrefetchLines;
-    @HotSpotVMFlag(name = "AllocatePrefetchStepSize") @Stable public int allocatePrefetchStepSize;
-    @HotSpotVMFlag(name = "AllocatePrefetchDistance") @Stable public int allocatePrefetchDistance;
-
-    @HotSpotVMFlag(name = "FlightRecorder", optional = true) @Stable public boolean flightRecorder;
-
-    @HotSpotVMField(name = "CompilerToVM::Data::Universe_collectedHeap", type = "CollectedHeap*", get = HotSpotVMField.Type.VALUE) @Stable private long universeCollectedHeap;
-    @HotSpotVMField(name = "CollectedHeap::_total_collections", type = "unsigned int", get = HotSpotVMField.Type.OFFSET) @Stable private int collectedHeapTotalCollectionsOffset;
-
-    public long gcTotalCollectionsAddress() {
-        return universeCollectedHeap + collectedHeapTotalCollectionsOffset;
-    }
-
-    @HotSpotVMFlag(name = "ReduceInitialCardMarks") @Stable public boolean useDeferredInitBarriers;
-
-    // Compressed Oops related values.
-    @HotSpotVMFlag(name = "UseCompressedOops") @Stable public boolean useCompressedOops;
-    @HotSpotVMFlag(name = "UseCompressedClassPointers") @Stable public boolean useCompressedClassPointers;
-
-    @HotSpotVMField(name = "CompilerToVM::Data::Universe_narrow_oop_base", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long narrowOopBase;
-    @HotSpotVMField(name = "CompilerToVM::Data::Universe_narrow_oop_shift", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int narrowOopShift;
-    @HotSpotVMFlag(name = "ObjectAlignmentInBytes") @Stable public int objectAlignment;
-
-    public final int minObjAlignment() {
-        return objectAlignment / heapWordSize;
-    }
-
-    public final int logMinObjAlignment() {
-        return (int) (Math.log(objectAlignment) / Math.log(2));
-    }
-
-    @HotSpotVMType(name = "narrowKlass", get = HotSpotVMType.Type.SIZE) @Stable public int narrowKlassSize;
-    @HotSpotVMField(name = "CompilerToVM::Data::Universe_narrow_klass_base", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long narrowKlassBase;
-    @HotSpotVMField(name = "CompilerToVM::Data::Universe_narrow_klass_shift", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int narrowKlassShift;
-    @HotSpotVMConstant(name = "LogKlassAlignmentInBytes") @Stable public int logKlassAlignment;
-
-    // CPU capabilities
-    @HotSpotVMFlag(name = "UseSSE") @Stable public int useSSE;
-    @HotSpotVMFlag(name = "UseAVX", archs = {"amd64"}) @Stable public int useAVX;
-
-    @HotSpotVMField(name = "Abstract_VM_Version::_features", type = "uint64_t", get = HotSpotVMField.Type.VALUE) @Stable public long vmVersionFeatures;
-
-    // AMD64 specific values
-    @HotSpotVMConstant(name = "VM_Version::CPU_CX8", archs = {"amd64"}) @Stable public long amd64CX8;
-    @HotSpotVMConstant(name = "VM_Version::CPU_CMOV", archs = {"amd64"}) @Stable public long amd64CMOV;
-    @HotSpotVMConstant(name = "VM_Version::CPU_FXSR", archs = {"amd64"}) @Stable public long amd64FXSR;
-    @HotSpotVMConstant(name = "VM_Version::CPU_HT", archs = {"amd64"}) @Stable public long amd64HT;
-    @HotSpotVMConstant(name = "VM_Version::CPU_MMX", archs = {"amd64"}) @Stable public long amd64MMX;
-    @HotSpotVMConstant(name = "VM_Version::CPU_3DNOW_PREFETCH", archs = {"amd64"}) @Stable public long amd643DNOWPREFETCH;
-    @HotSpotVMConstant(name = "VM_Version::CPU_SSE", archs = {"amd64"}) @Stable public long amd64SSE;
-    @HotSpotVMConstant(name = "VM_Version::CPU_SSE2", archs = {"amd64"}) @Stable public long amd64SSE2;
-    @HotSpotVMConstant(name = "VM_Version::CPU_SSE3", archs = {"amd64"}) @Stable public long amd64SSE3;
-    @HotSpotVMConstant(name = "VM_Version::CPU_SSSE3", archs = {"amd64"}) @Stable public long amd64SSSE3;
-    @HotSpotVMConstant(name = "VM_Version::CPU_SSE4A", archs = {"amd64"}) @Stable public long amd64SSE4A;
-    @HotSpotVMConstant(name = "VM_Version::CPU_SSE4_1", archs = {"amd64"}) @Stable public long amd64SSE41;
-    @HotSpotVMConstant(name = "VM_Version::CPU_SSE4_2", archs = {"amd64"}) @Stable public long amd64SSE42;
-    @HotSpotVMConstant(name = "VM_Version::CPU_POPCNT", archs = {"amd64"}) @Stable public long amd64POPCNT;
-    @HotSpotVMConstant(name = "VM_Version::CPU_LZCNT", archs = {"amd64"}) @Stable public long amd64LZCNT;
-    @HotSpotVMConstant(name = "VM_Version::CPU_TSC", archs = {"amd64"}) @Stable public long amd64TSC;
-    @HotSpotVMConstant(name = "VM_Version::CPU_TSCINV", archs = {"amd64"}) @Stable public long amd64TSCINV;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX", archs = {"amd64"}) @Stable public long amd64AVX;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX2", archs = {"amd64"}) @Stable public long amd64AVX2;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AES", archs = {"amd64"}) @Stable public long amd64AES;
-    @HotSpotVMConstant(name = "VM_Version::CPU_ERMS", archs = {"amd64"}) @Stable public long amd64ERMS;
-    @HotSpotVMConstant(name = "VM_Version::CPU_CLMUL", archs = {"amd64"}) @Stable public long amd64CLMUL;
-    @HotSpotVMConstant(name = "VM_Version::CPU_BMI1", archs = {"amd64"}) @Stable public long amd64BMI1;
-    @HotSpotVMConstant(name = "VM_Version::CPU_BMI2", archs = {"amd64"}) @Stable public long amd64BMI2;
-    @HotSpotVMConstant(name = "VM_Version::CPU_RTM", archs = {"amd64"}) @Stable public long amd64RTM;
-    @HotSpotVMConstant(name = "VM_Version::CPU_ADX", archs = {"amd64"}) @Stable public long amd64ADX;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512F", archs = {"amd64"}) @Stable public long amd64AVX512F;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512DQ", archs = {"amd64"}) @Stable public long amd64AVX512DQ;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512PF", archs = {"amd64"}) @Stable public long amd64AVX512PF;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512ER", archs = {"amd64"}) @Stable public long amd64AVX512ER;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512CD", archs = {"amd64"}) @Stable public long amd64AVX512CD;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512BW", archs = {"amd64"}) @Stable public long amd64AVX512BW;
-    @HotSpotVMConstant(name = "VM_Version::CPU_AVX512VL", archs = {"amd64"}) @Stable public long amd64AVX512VL;
-    @HotSpotVMConstant(name = "VM_Version::CPU_SHA", archs = {"amd64"}) @Stable public long amd64SHA;
-
-    // SPARC specific values
-    @HotSpotVMConstant(name = "VM_Version::vis3_instructions_m", archs = {"sparc"}) @Stable public int sparcVis3Instructions;
-    @HotSpotVMConstant(name = "VM_Version::vis2_instructions_m", archs = {"sparc"}) @Stable public int sparcVis2Instructions;
-    @HotSpotVMConstant(name = "VM_Version::vis1_instructions_m", archs = {"sparc"}) @Stable public int sparcVis1Instructions;
-    @HotSpotVMConstant(name = "VM_Version::cbcond_instructions_m", archs = {"sparc"}) @Stable public int sparcCbcondInstructions;
-    @HotSpotVMConstant(name = "VM_Version::v8_instructions_m", archs = {"sparc"}) @Stable public int sparcV8Instructions;
-    @HotSpotVMConstant(name = "VM_Version::hardware_mul32_m", archs = {"sparc"}) @Stable public int sparcHardwareMul32;
-    @HotSpotVMConstant(name = "VM_Version::hardware_div32_m", archs = {"sparc"}) @Stable public int sparcHardwareDiv32;
-    @HotSpotVMConstant(name = "VM_Version::hardware_fsmuld_m", archs = {"sparc"}) @Stable public int sparcHardwareFsmuld;
-    @HotSpotVMConstant(name = "VM_Version::hardware_popc_m", archs = {"sparc"}) @Stable public int sparcHardwarePopc;
-    @HotSpotVMConstant(name = "VM_Version::v9_instructions_m", archs = {"sparc"}) @Stable public int sparcV9Instructions;
-    @HotSpotVMConstant(name = "VM_Version::sun4v_m", archs = {"sparc"}) @Stable public int sparcSun4v;
-    @HotSpotVMConstant(name = "VM_Version::blk_init_instructions_m", archs = {"sparc"}) @Stable public int sparcBlkInitInstructions;
-    @HotSpotVMConstant(name = "VM_Version::fmaf_instructions_m", archs = {"sparc"}) @Stable public int sparcFmafInstructions;
-    @HotSpotVMConstant(name = "VM_Version::fmau_instructions_m", archs = {"sparc"}) @Stable public int sparcFmauInstructions;
-    @HotSpotVMConstant(name = "VM_Version::sparc64_family_m", archs = {"sparc"}) @Stable public int sparcSparc64Family;
-    @HotSpotVMConstant(name = "VM_Version::M_family_m", archs = {"sparc"}) @Stable public int sparcMFamily;
-    @HotSpotVMConstant(name = "VM_Version::T_family_m", archs = {"sparc"}) @Stable public int sparcTFamily;
-    @HotSpotVMConstant(name = "VM_Version::T1_model_m", archs = {"sparc"}) @Stable public int sparcT1Model;
-    @HotSpotVMConstant(name = "VM_Version::sparc5_instructions_m", archs = {"sparc"}) @Stable public int sparcSparc5Instructions;
-    @HotSpotVMConstant(name = "VM_Version::aes_instructions_m", archs = {"sparc"}) @Stable public int sparcAesInstructions;
-    @HotSpotVMConstant(name = "VM_Version::sha1_instruction_m", archs = {"sparc"}) @Stable public int sparcSha1Instruction;
-    @HotSpotVMConstant(name = "VM_Version::sha256_instruction_m", archs = {"sparc"}) @Stable public int sparcSha256Instruction;
-    @HotSpotVMConstant(name = "VM_Version::sha512_instruction_m", archs = {"sparc"}) @Stable public int sparcSha512Instruction;
-
-    @HotSpotVMFlag(name = "UseBlockZeroing", archs = {"sparc"}) @Stable public boolean useBlockZeroing;
-    @HotSpotVMFlag(name = "BlockZeroingLowLimit", archs = {"sparc"}) @Stable public int blockZeroingLowLimit;
-
-    @HotSpotVMFlag(name = "StackShadowPages") @Stable public int stackShadowPages;
-    @HotSpotVMFlag(name = "StackReservedPages") @Stable public int stackReservedPages;
-    @HotSpotVMFlag(name = "UseStackBanging") @Stable public boolean useStackBanging;
-    @HotSpotVMConstant(name = "STACK_BIAS") @Stable public int stackBias;
-    @HotSpotVMField(name = "CompilerToVM::Data::vm_page_size", type = "int", get = HotSpotVMField.Type.VALUE) @Stable public int vmPageSize;
-
-    // offsets, ...
-    @HotSpotVMField(name = "oopDesc::_mark", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int markOffset;
-    @HotSpotVMField(name = "oopDesc::_metadata._klass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int hubOffset;
-
-    @HotSpotVMField(name = "Klass::_prototype_header", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int prototypeMarkWordOffset;
-    @HotSpotVMField(name = "Klass::_subklass", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int subklassOffset;
-    @HotSpotVMField(name = "Klass::_next_sibling", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int nextSiblingOffset;
-    @HotSpotVMField(name = "Klass::_super_check_offset", type = "juint", get = HotSpotVMField.Type.OFFSET) @Stable public int superCheckOffsetOffset;
-    @HotSpotVMField(name = "Klass::_secondary_super_cache", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int secondarySuperCacheOffset;
-    @HotSpotVMField(name = "Klass::_secondary_supers", type = "Array<Klass*>*", get = HotSpotVMField.Type.OFFSET) @Stable public int secondarySupersOffset;
+    final int prototypeMarkWordOffset = getFieldOffset("Klass::_prototype_header", Integer.class, "markOop");
+    final int subklassOffset = getFieldOffset("Klass::_subklass", Integer.class, "Klass*");
+    final int nextSiblingOffset = getFieldOffset("Klass::_next_sibling", Integer.class, "Klass*");
+    final int superCheckOffsetOffset = getFieldOffset("Klass::_super_check_offset", Integer.class, "juint");
+    final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*");
 
     /**
      * The offset of the _java_mirror field (of type {@link Class}) in a Klass.
      */
-    @HotSpotVMField(name = "Klass::_java_mirror", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int classMirrorOffset;
+    final int classMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "oop");
 
-    @HotSpotVMField(name = "Klass::_super", type = "Klass*", get = HotSpotVMField.Type.OFFSET) @Stable public int klassSuperKlassOffset;
-    @HotSpotVMField(name = "Klass::_modifier_flags", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int klassModifierFlagsOffset;
-    @HotSpotVMField(name = "Klass::_access_flags", type = "AccessFlags", get = HotSpotVMField.Type.OFFSET) @Stable public int klassAccessFlagsOffset;
-    @HotSpotVMField(name = "Klass::_layout_helper", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int klassLayoutHelperOffset;
-    @HotSpotVMField(name = "Klass::_name", type = "Symbol*", get = HotSpotVMField.Type.OFFSET) @Stable public int klassNameOffset;
+    final int klassAccessFlagsOffset = getFieldOffset("Klass::_access_flags", Integer.class, "AccessFlags");
+    final int klassLayoutHelperOffset = getFieldOffset("Klass::_layout_helper", Integer.class, "jint");
 
-    @HotSpotVMConstant(name = "Klass::_lh_neutral_value") @Stable public int klassLayoutHelperNeutralValue;
-    @HotSpotVMConstant(name = "Klass::_lh_instance_slow_path_bit") @Stable public int klassLayoutHelperInstanceSlowPathBit;
-    @HotSpotVMConstant(name = "Klass::_lh_log2_element_size_shift") @Stable public int layoutHelperLog2ElementSizeShift;
-    @HotSpotVMConstant(name = "Klass::_lh_log2_element_size_mask") @Stable public int layoutHelperLog2ElementSizeMask;
-    @HotSpotVMConstant(name = "Klass::_lh_element_type_shift") @Stable public int layoutHelperElementTypeShift;
-    @HotSpotVMConstant(name = "Klass::_lh_element_type_mask") @Stable public int layoutHelperElementTypeMask;
-    @HotSpotVMConstant(name = "Klass::_lh_header_size_shift") @Stable public int layoutHelperHeaderSizeShift;
-    @HotSpotVMConstant(name = "Klass::_lh_header_size_mask") @Stable public int layoutHelperHeaderSizeMask;
-    @HotSpotVMConstant(name = "Klass::_lh_array_tag_shift") @Stable public int layoutHelperArrayTagShift;
-    @HotSpotVMConstant(name = "Klass::_lh_array_tag_type_value") @Stable public int layoutHelperArrayTagTypeValue;
-    @HotSpotVMConstant(name = "Klass::_lh_array_tag_obj_value") @Stable public int layoutHelperArrayTagObjectValue;
+    final int klassLayoutHelperNeutralValue = getConstant("Klass::_lh_neutral_value", Integer.class);
+    final int klassLayoutHelperInstanceSlowPathBit = getConstant("Klass::_lh_instance_slow_path_bit", Integer.class);
 
-    /**
-     * This filters out the bit that differentiates a type array from an object array.
-     */
-    public int layoutHelperElementTypePrimitiveInPlace() {
-        return (layoutHelperArrayTagTypeValue & ~layoutHelperArrayTagObjectValue) << layoutHelperArrayTagShift;
-    }
+    final int vtableEntrySize = getTypeSize("vtableEntry");
+    final int vtableEntryMethodOffset = getFieldOffset("vtableEntry::_method", Integer.class, "Method*");
 
-    /**
-     * Bit pattern in the klass layout helper that can be used to identify arrays.
-     */
-    public final int arrayKlassLayoutHelperIdentifier = 0x80000000;
+    final int instanceKlassSourceFileNameIndexOffset = getFieldOffset("InstanceKlass::_source_file_name_index", Integer.class, "u2");
+    final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
+    final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
+    final int instanceKlassFieldsOffset = getFieldOffset("InstanceKlass::_fields", Integer.class, "Array<u2>*");
+    final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
+    final int klassVtableLengthOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_length_offset", Integer.class, "int");
 
-    @HotSpotVMType(name = "vtableEntry", get = HotSpotVMType.Type.SIZE) @Stable public int vtableEntrySize;
-    @HotSpotVMField(name = "vtableEntry::_method", type = "Method*", get = HotSpotVMField.Type.OFFSET) @Stable public int vtableEntryMethodOffset;
+    final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
+    final int instanceKlassStateFullyIn