changeset 13440:190dd9cd1882

Merge
author iignatyev
date Wed, 02 Aug 2017 15:59:33 +0000
parents 84827cfd116a a77c680f1535
children b69f277b24f4
files src/os_cpu/solaris_x86/vm/solaris_x86_32.il src/os_cpu/solaris_x86/vm/solaris_x86_32.s
diffstat 74 files changed, 1513 insertions(+), 1349 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Aug 02 08:53:18 2017 -0700
+++ b/.hgtags	Wed Aug 02 15:59:33 2017 +0000
@@ -592,3 +592,11 @@
 070aa7a2eb14c4645f7eb31384cba0a2ba72a4b5 jdk-10+12
 8f04d457168b9f1f4a1b2c37f49e0513ca9d33a7 jdk-9+175
 a9da03357f190807591177fe9846d6e68ad64fc0 jdk-10+13
+e920b4d008d914f3414bd4630b58837cf0b7f08d jdk-10+14
+2ab74e5dbdc2b6a962c865500cafd23cf387dc60 jdk-9+176
+1ca8f038fceb88c640badf9bd18905205bc63b43 jdk-9+177
+c1f3649a3a42f124b418a5a916dbad13d059b757 jdk-10+15
+2fe2a593e8ebf3a9e4dcd9ba3333a7b43126589d jdk-10+16
+9d032191f82fca5ba0aac98682f69c4ff0f1283d jdk-9+178
+d2661aa42bff322badbe6c1337fc638d2e0f5730 jdk-9+179
+73e2cb8700bfa51304bd4b02f224620859a3f600 jdk-10+17
--- a/src/cpu/aarch64/vm/aarch64.ad	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/aarch64/vm/aarch64.ad	Wed Aug 02 15:59:33 2017 +0000
@@ -14693,7 +14693,7 @@
   ins_pipe(icmp_reg_reg);
 %}
 
-instruct compL_reg_immI0(rFlagsReg cr, iRegL op1, immI0 zero)
+instruct compL_reg_immL0(rFlagsReg cr, iRegL op1, immL0 zero)
 %{
   match(Set cr (CmpL op1 zero));
 
@@ -14735,6 +14735,62 @@
   ins_pipe(icmp_reg_imm);
 %}
 
+instruct compUL_reg_reg(rFlagsRegU cr, iRegL op1, iRegL op2)
+%{
+  match(Set cr (CmpUL op1 op2));
+
+  effect(DEF cr, USE op1, USE op2);
+
+  ins_cost(INSN_COST);
+  format %{ "cmp  $op1, $op2" %}
+
+  ins_encode(aarch64_enc_cmp(op1, op2));
+
+  ins_pipe(icmp_reg_reg);
+%}
+
+instruct compUL_reg_immL0(rFlagsRegU cr, iRegL op1, immL0 zero)
+%{
+  match(Set cr (CmpUL op1 zero));
+
+  effect(DEF cr, USE op1);
+
+  ins_cost(INSN_COST);
+  format %{ "tst  $op1" %}
+
+  ins_encode(aarch64_enc_cmp_imm_addsub(op1, zero));
+
+  ins_pipe(icmp_reg_imm);
+%}
+
+instruct compUL_reg_immLAddSub(rFlagsRegU cr, iRegL op1, immLAddSub op2)
+%{
+  match(Set cr (CmpUL op1 op2));
+
+  effect(DEF cr, USE op1);
+
+  ins_cost(INSN_COST);
+  format %{ "cmp  $op1, $op2" %}
+
+  ins_encode(aarch64_enc_cmp_imm_addsub(op1, op2));
+
+  ins_pipe(icmp_reg_imm);
+%}
+
+instruct compUL_reg_immL(rFlagsRegU cr, iRegL op1, immL op2)
+%{
+  match(Set cr (CmpUL op1 op2));
+
+  effect(DEF cr, USE op1);
+
+  ins_cost(INSN_COST * 2);
+  format %{ "cmp  $op1, $op2" %}
+
+  ins_encode(aarch64_enc_cmp_imm(op1, op2));
+
+  ins_pipe(icmp_reg_imm);
+%}
+
 instruct compP_reg_reg(rFlagsRegU cr, iRegP op1, iRegP op2)
 %{
   match(Set cr (CmpP op1 op2));
@@ -15219,7 +15275,7 @@
 %}
 
 instruct cmpUL_imm0_branch(cmpOpUEqNeLtGe cmp, iRegL op1, immL0 op2, label labl, rFlagsRegU cr) %{
-  match(If cmp (CmpU op1 op2));
+  match(If cmp (CmpUL op1 op2));
   effect(USE labl);
 
   ins_cost(BRANCH_COST);
--- a/src/cpu/aarch64/vm/c2_globals_aarch64.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/aarch64/vm/c2_globals_aarch64.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -49,12 +49,11 @@
 define_pd_global(intx, FLOATPRESSURE,                64);
 define_pd_global(intx, FreqInlineSize,               325);
 define_pd_global(intx, MinJumpTableSize,             10);
-define_pd_global(intx, INTPRESSURE,                  25);
+define_pd_global(intx, INTPRESSURE,                  24);
 define_pd_global(intx, InteriorEntryAlignment,       16);
 define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K));
 define_pd_global(intx, LoopUnrollLimit,              60);
 define_pd_global(intx, LoopPercentProfileLimit,      10);
-define_pd_global(intx, PostLoopMultiversioning,      false);
 // InitialCodeCacheSize derived from specjbb2000 run.
 define_pd_global(intx, InitialCodeCacheSize,         2496*K); // Integral multiple of CodeCacheExpansionSize
 define_pd_global(intx, CodeCacheExpansionSize,       64*K);
--- a/src/cpu/arm/vm/arm.ad	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/arm/vm/arm.ad	Wed Aug 02 15:59:33 2017 +0000
@@ -2695,6 +2695,30 @@
   format %{ "apsr_L_LEGT" %}
   interface(REG_INTER);
 %}
+
+operand flagsRegUL_LTGE() %{
+  constraint(ALLOC_IN_RC(int_flags));
+  match(RegFlags);
+
+  format %{ "apsr_UL_LTGE" %}
+  interface(REG_INTER);
+%}
+
+operand flagsRegUL_EQNE() %{
+  constraint(ALLOC_IN_RC(int_flags));
+  match(RegFlags);
+
+  format %{ "apsr_UL_EQNE" %}
+  interface(REG_INTER);
+%}
+
+operand flagsRegUL_LEGT() %{
+  constraint(ALLOC_IN_RC(int_flags));
+  match(RegFlags);
+
+  format %{ "apsr_UL_LEGT" %}
+  interface(REG_INTER);
+%}
 #endif
 
 // Condition Code Register, floating comparisons, unordered same as "less".
@@ -3249,6 +3273,39 @@
   %}
 %}
 
+operand cmpOpUL() %{
+  match(Bool);
+
+  format %{ "UL" %}
+  interface(COND_INTER) %{
+    equal(0x0);
+    not_equal(0x1);
+    less(0x3);
+    greater_equal(0x2);
+    less_equal(0x9);
+    greater(0x8);
+    overflow(0x0); // unsupported/unimplemented
+    no_overflow(0x0); // unsupported/unimplemented
+  %}
+%}
+
+operand cmpOpUL_commute() %{
+  match(Bool);
+
+  format %{ "UL" %}
+  interface(COND_INTER) %{
+    equal(0x0);
+    not_equal(0x1);
+    less(0x8);
+    greater_equal(0x9);
+    less_equal(0x2);
+    greater(0x3);
+    overflow(0x0); // unsupported/unimplemented
+    no_overflow(0x0); // unsupported/unimplemented
+  %}
+%}
+
+
 //----------OPERAND CLASSES----------------------------------------------------
 // Operand Classes are groups of operands that are used to simplify
 // instruction definitions by not requiring the AD writer to specify separate
@@ -10467,6 +10524,17 @@
   %}
   ins_pipe(ialu_cconly_reg_reg);
 %}
+
+instruct compUL_iReg(flagsRegU xcc, iRegL op1, iRegL op2) %{
+  match(Set xcc (CmpUL op1 op2));
+
+  size(4);
+  format %{ "CMP     $op1,$op2\t! unsigned long" %}
+  ins_encode %{
+    __ cmp($op1$$Register, $op2$$Register);
+  %}
+  ins_pipe(ialu_cconly_reg_reg);
+%}
 #else
 instruct compL_reg_reg_LTGE(flagsRegL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
   match(Set xcc (CmpL op1 op2));
@@ -10481,6 +10549,20 @@
   %}
   ins_pipe(ialu_cconly_reg_reg);
 %}
+
+instruct compUL_reg_reg_LTGE(flagsRegUL_LTGE xcc, iRegL op1, iRegL op2, iRegL tmp) %{
+  match(Set xcc (CmpUL op1 op2));
+  effect(DEF xcc, USE op1, USE op2, TEMP tmp);
+
+  size(8);
+  format %{ "SUBS    $tmp,$op1.low,$op2.low\t\t! unsigned long\n\t"
+            "SBCS    $tmp,$op1.hi,$op2.hi" %}
+  ins_encode %{
+    __ subs($tmp$$Register, $op1$$Register, $op2$$Register);
+    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), $op2$$Register->successor());
+  %}
+  ins_pipe(ialu_cconly_reg_reg);
+%}
 #endif
 
 #ifdef AARCH64
@@ -10496,6 +10578,19 @@
 
   ins_pipe(ialu_cconly_reg_imm);
 %}
+
+instruct compUL_reg_con(flagsRegU xcc, iRegL op1, aimmL con) %{
+  match(Set xcc (CmpUL op1 con));
+  effect(DEF xcc, USE op1, USE con);
+
+  size(8);
+  format %{ "CMP     $op1,$con\t\t! unsigned long"  %}
+  ins_encode %{
+    __ cmp($op1$$Register, $con$$constant);
+  %}
+
+  ins_pipe(ialu_cconly_reg_imm);
+%}
 #else
 instruct compL_reg_reg_EQNE(flagsRegL_EQNE xcc, iRegL op1, iRegL op2) %{
   match(Set xcc (CmpL op1 op2));
@@ -10575,6 +10670,85 @@
 
   ins_pipe(ialu_cconly_reg_reg);
 %}
+
+instruct compUL_reg_reg_EQNE(flagsRegUL_EQNE xcc, iRegL op1, iRegL op2) %{
+  match(Set xcc (CmpUL op1 op2));
+  effect(DEF xcc, USE op1, USE op2);
+
+  size(8);
+  format %{ "TEQ    $op1.hi,$op2.hi\t\t! unsigned long\n\t"
+            "TEQ.eq $op1.lo,$op2.lo" %}
+  ins_encode %{
+    __ teq($op1$$Register->successor(), $op2$$Register->successor());
+    __ teq($op1$$Register, $op2$$Register, eq);
+  %}
+  ins_pipe(ialu_cconly_reg_reg);
+%}
+
+instruct compUL_reg_reg_LEGT(flagsRegUL_LEGT xcc, iRegL op1, iRegL op2, iRegL tmp) %{
+  match(Set xcc (CmpUL op1 op2));
+  effect(DEF xcc, USE op1, USE op2, TEMP tmp);
+
+  size(8);
+  format %{ "SUBS    $tmp,$op2.low,$op1.low\t\t! unsigned long\n\t"
+            "SBCS    $tmp,$op2.hi,$op1.hi" %}
+  ins_encode %{
+    __ subs($tmp$$Register, $op2$$Register, $op1$$Register);
+    __ sbcs($tmp$$Register->successor(), $op2$$Register->successor(), $op1$$Register->successor());
+  %}
+  ins_pipe(ialu_cconly_reg_reg);
+%}
+
+// TODO: try immLRot2 instead, (0, $con$$constant) becomes
+// (hi($con$$constant), lo($con$$constant)) becomes
+instruct compUL_reg_con_LTGE(flagsRegUL_LTGE xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
+  match(Set xcc (CmpUL op1 con));
+  effect(DEF xcc, USE op1, USE con, TEMP tmp);
+
+  size(8);
+  format %{ "SUBS    $tmp,$op1.low,$con\t\t! unsigned long\n\t"
+            "SBCS    $tmp,$op1.hi,0" %}
+  ins_encode %{
+    __ subs($tmp$$Register, $op1$$Register, $con$$constant);
+    __ sbcs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
+  %}
+
+  ins_pipe(ialu_cconly_reg_reg);
+%}
+
+// TODO: try immLRot2 instead, (0, $con$$constant) becomes
+// (hi($con$$constant), lo($con$$constant)) becomes
+instruct compUL_reg_con_EQNE(flagsRegUL_EQNE xcc, iRegL op1, immLlowRot con) %{
+  match(Set xcc (CmpUL op1 con));
+  effect(DEF xcc, USE op1, USE con);
+
+  size(8);
+  format %{ "TEQ    $op1.hi,0\t\t! unsigned long\n\t"
+            "TEQ.eq $op1.lo,$con" %}
+  ins_encode %{
+    __ teq($op1$$Register->successor(), 0);
+    __ teq($op1$$Register, $con$$constant, eq);
+  %}
+
+  ins_pipe(ialu_cconly_reg_reg);
+%}
+
+// TODO: try immLRot2 instead, (0, $con$$constant) becomes
+// (hi($con$$constant), lo($con$$constant)) becomes
+instruct compUL_reg_con_LEGT(flagsRegUL_LEGT xcc, iRegL op1, immLlowRot con, iRegL tmp) %{
+  match(Set xcc (CmpUL op1 con));
+  effect(DEF xcc, USE op1, USE con, TEMP tmp);
+
+  size(8);
+  format %{ "RSBS    $tmp,$op1.low,$con\t\t! unsigned long\n\t"
+            "RSCS    $tmp,$op1.hi,0" %}
+  ins_encode %{
+    __ rsbs($tmp$$Register, $op1$$Register, $con$$constant);
+    __ rscs($tmp$$Register->successor(), $op1$$Register->successor(), 0);
+  %}
+
+  ins_pipe(ialu_cconly_reg_reg);
+%}
 #endif
 
 /* instruct testL_reg_reg(flagsRegL xcc, iRegL op1, iRegL op2, immL0 zero) %{ */
@@ -11126,6 +11300,48 @@
   %}
   ins_pipe(br_cc);
 %}
+
+instruct branchConUL_LTGE(cmpOpUL cmp, flagsRegUL_LTGE xcc, label labl) %{
+  match(If cmp xcc);
+  effect(USE labl);
+  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
+
+  size(4);
+  ins_cost(BRANCH_COST);
+  format %{ "B$cmp  $xcc,$labl" %}
+  ins_encode %{
+    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
+  %}
+  ins_pipe(br_cc);
+%}
+
+instruct branchConUL_EQNE(cmpOpUL cmp, flagsRegUL_EQNE xcc, label labl) %{
+  match(If cmp xcc);
+  effect(USE labl);
+  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
+
+  size(4);
+  ins_cost(BRANCH_COST);
+  format %{ "B$cmp  $xcc,$labl" %}
+  ins_encode %{
+    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
+  %}
+  ins_pipe(br_cc);
+%}
+
+instruct branchConUL_LEGT(cmpOpUL_commute cmp, flagsRegUL_LEGT xcc, label labl) %{
+  match(If cmp xcc);
+  effect(USE labl);
+  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
+
+  size(4);
+  ins_cost(BRANCH_COST);
+  format %{ "B$cmp  $xcc,$labl" %}
+  ins_encode %{
+    __ b(*($labl$$label), (AsmCondition)($cmp$$cmpcode));
+  %}
+  ins_pipe(br_cc);
+%}
 #endif
 
 instruct branchLoopEnd(cmpOp cmp, flagsReg icc, label labl) %{
--- a/src/cpu/arm/vm/c2_globals_arm.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/arm/vm/c2_globals_arm.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -70,7 +70,6 @@
 define_pd_global(bool, ResizeTLAB,                   true);
 define_pd_global(intx, LoopUnrollLimit,              60); // Design center runs on 1.3.1
 define_pd_global(intx, LoopPercentProfileLimit,      10);
-define_pd_global(intx, PostLoopMultiversioning,      false);
 define_pd_global(intx, MinJumpTableSize,             16);
 
 // Peephole and CISC spilling both break the graph, and so makes the
--- a/src/cpu/ppc/vm/c2_globals_ppc.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/ppc/vm/c2_globals_ppc.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -55,7 +55,6 @@
 define_pd_global(bool, ResizeTLAB,                   true);
 define_pd_global(intx, LoopUnrollLimit,              60);
 define_pd_global(intx, LoopPercentProfileLimit,      10);
-define_pd_global(intx, PostLoopMultiversioning,      false);
 
 // Peephole and CISC spilling both break the graph, and so make the
 // scheduler sick.
--- a/src/cpu/ppc/vm/ppc.ad	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/ppc/vm/ppc.ad	Wed Aug 02 15:59:33 2017 +0000
@@ -11394,6 +11394,29 @@
   ins_pipe(pipe_class_compare);
 %}
 
+// Added CmpUL for LoopPredicate.
+instruct cmpUL_reg_reg(flagsReg crx, iRegLsrc src1, iRegLsrc src2) %{
+  match(Set crx (CmpUL src1 src2));
+  format %{ "CMPLD   $crx, $src1, $src2" %}
+  size(4);
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_cmpl);
+    __ cmpld($crx$$CondRegister, $src1$$Register, $src2$$Register);
+  %}
+  ins_pipe(pipe_class_compare);
+%}
+
+instruct cmpUL_reg_imm16(flagsReg crx, iRegLsrc src1, uimmL16 src2) %{
+  match(Set crx (CmpUL src1 src2));
+  format %{ "CMPLDI  $crx, $src1, $src2" %}
+  size(4);
+  ins_encode %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_cmpli);
+    __ cmpldi($crx$$CondRegister, $src1$$Register, $src2$$constant);
+  %}
+  ins_pipe(pipe_class_compare);
+%}
+
 instruct testL_reg_reg(flagsRegCR0 cr0, iRegLsrc src1, iRegLsrc src2, immL_0 zero) %{
   match(Set cr0 (CmpL (AndL src1 src2) zero));
   // r0 is killed
--- a/src/cpu/s390/vm/c2_globals_s390.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/s390/vm/c2_globals_s390.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -56,7 +56,6 @@
 define_pd_global(bool, ResizeTLAB,                   true);
 define_pd_global(intx, LoopUnrollLimit,              60);
 define_pd_global(intx, LoopPercentProfileLimit,      10);
-define_pd_global(intx, PostLoopMultiversioning,      false);
 define_pd_global(intx, MinJumpTableSize,             18);
 
 // Peephole and CISC spilling both break the graph, and so makes the
--- a/src/cpu/s390/vm/s390.ad	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/s390/vm/s390.ad	Wed Aug 02 15:59:33 2017 +0000
@@ -8470,6 +8470,24 @@
 %}
 
 //  LONG unsigned
+// Added CmpUL for LoopPredicate.
+instruct compUL_reg_reg(flagsReg cr, iRegL op1, iRegL op2) %{
+  match(Set cr (CmpUL op1 op2));
+  size(4);
+  format %{ "CLGR    $op1,$op2\t # long" %}
+  opcode(CLGR_ZOPC);
+  ins_encode(z_rreform(op1, op2));
+  ins_pipe(pipe_class_dummy);
+%}
+
+instruct compUL_reg_imm32(flagsReg cr, iRegL op1, uimmL32 con) %{
+  match(Set cr (CmpUL op1 con));
+  size(6);
+  format %{ "CLGFI   $op1,$con" %}
+  opcode(CLGFI_ZOPC);
+  ins_encode(z_rilform_unsigned(op1, con));
+  ins_pipe(pipe_class_dummy);
+%}
 
 //  PTR unsigned
 
--- a/src/cpu/s390/vm/stubGenerator_s390.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/s390/vm/stubGenerator_s390.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -1683,7 +1683,7 @@
   //   src    must designate an even/odd register pair, holding the address/length of the original message
 
   // Helper function which generates code to
-  //  - load the function code in register fCode (== Z_R0)
+  //  - load the function code in register fCode (== Z_R0).
   //  - load the data block length (depends on cipher function) into register srclen if requested.
   //  - is_decipher switches between cipher/decipher function codes
   //  - set_len requests (if true) loading the data block length in register srclen
@@ -1695,13 +1695,13 @@
       bool  identical_dataBlk_len =  (VM_Version::Cipher::_AES128_dataBlk == VM_Version::Cipher::_AES192_dataBlk)
                                   && (VM_Version::Cipher::_AES128_dataBlk == VM_Version::Cipher::_AES256_dataBlk);
       // Expanded key length is 44/52/60 * 4 bytes for AES-128/AES-192/AES-256.
-      __ z_cghi(keylen, 52);
-
-      __ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode);
+      __ z_cghi(keylen, 52); // Check only once at the beginning. keylen and fCode may share the same register.
+
+      __ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode);
       if (!identical_dataBlk_len) {
-        __ z_lghi(srclen, VM_Version::Cipher::_AES256_dataBlk);
+        __ z_lghi(srclen, VM_Version::Cipher::_AES128_dataBlk);
       }
-      __ z_brh(fCode_set);  // keyLen >  52: AES256
+      __ z_brl(fCode_set);  // keyLen <  52: AES128
 
       __ z_lghi(fCode, VM_Version::Cipher::_AES192 + mode);
       if (!identical_dataBlk_len) {
@@ -1709,11 +1709,11 @@
       }
       __ z_bre(fCode_set);  // keyLen == 52: AES192
 
-      __ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode);
+      __ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode);
       if (!identical_dataBlk_len) {
-        __ z_lghi(srclen, VM_Version::Cipher::_AES128_dataBlk);
+        __ z_lghi(srclen, VM_Version::Cipher::_AES256_dataBlk);
       }
-      // __ z_brl(fCode_set);  // keyLen <  52: AES128           // fallthru
+      // __ z_brh(fCode_set);  // keyLen <  52: AES128           // fallthru
 
       __ bind(fCode_set);
       if (identical_dataBlk_len) {
@@ -1724,6 +1724,54 @@
   }
 
   // Push a parameter block for the cipher/decipher instruction on the stack.
+  // Layout of the additional stack space allocated for AES_cipherBlockChaining:
+  //
+  //   |        |
+  //   +--------+ <-- SP before expansion
+  //   |        |
+  //   :        :  alignment loss, 0..(AES_parmBlk_align-8) bytes
+  //   |        |
+  //   +--------+
+  //   |        |
+  //   :        :  space for parameter block, size VM_Version::Cipher::_AES*_parmBlk_C
+  //   |        |
+  //   +--------+ <-- parmBlk, octoword-aligned, start of parameter block
+  //   |        |
+  //   :        :  additional stack space for spills etc., size AES_parmBlk_addspace, DW @ Z_SP not usable!!!
+  //   |        |
+  //   +--------+ <-- Z_SP after expansion
+
+  void generate_push_Block(int dataBlk_len, int parmBlk_len, int crypto_fCode,
+                           Register parmBlk, Register keylen, Register fCode, Register cv, Register key) {
+    const int AES_parmBlk_align    = 32;  // octoword alignment.
+    const int AES_parmBlk_addspace = 24;  // Must be sufficiently large to hold all spilled registers
+                                          // (currently 2) PLUS 1 DW for the frame pointer.
+
+    const int cv_len     = dataBlk_len;
+    const int key_len    = parmBlk_len - cv_len;
+    // This len must be known at JIT compile time. Only then are we able to recalc the SP before resize.
+    // We buy this knowledge by wasting some (up to AES_parmBlk_align) bytes of stack space.
+    const int resize_len = cv_len + key_len + AES_parmBlk_align + AES_parmBlk_addspace;
+
+    // Use parmBlk as temp reg here to hold the frame pointer.
+    __ resize_frame(-resize_len, parmBlk, true);
+
+    // calculate parmBlk address from updated (resized) SP.
+    __ add2reg(parmBlk, resize_len - (cv_len + key_len), Z_SP);
+    __ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // Align parameter block.
+
+    // There is room for stuff in the range [parmBlk-AES_parmBlk_addspace+8, parmBlk).
+    __ z_stg(keylen,  -8, parmBlk);                        // Spill keylen for later use.
+
+    // calculate (SP before resize) from updated SP.
+    __ add2reg(keylen, resize_len, Z_SP);                  // keylen holds prev SP for now.
+    __ z_stg(keylen, -16, parmBlk);                        // Spill prev SP for easy revert.
+
+    __ z_mvc(0,      cv_len-1,  parmBlk, 0, cv);     // Copy cv.
+    __ z_mvc(cv_len, key_len-1, parmBlk, 0, key);    // Copy key.
+    __ z_lghi(fCode, crypto_fCode);
+  }
+
   // NOTE:
   //   Before returning, the stub has to copy the chaining value from
   //   the parmBlk, where it was updated by the crypto instruction, back
@@ -1732,17 +1780,14 @@
   //   the key length across the KMC instruction. We do so by spilling it to the stack,
   //   just preceding the parmBlk (at (parmBlk - 8)).
   void generate_push_parmBlk(Register keylen, Register fCode, Register parmBlk, Register key, Register cv, bool is_decipher) {
-    const int AES_parmBlk_align    = 32;
-    const int AES_parmBlk_addspace = AES_parmBlk_align; // Must be multiple of AES_parmblk_align.
-    int       cv_len, key_len;
     int       mode = is_decipher ? VM_Version::CipherMode::decipher : VM_Version::CipherMode::cipher;
     Label     parmBlk_128, parmBlk_192, parmBlk_256, parmBlk_set;
 
     BLOCK_COMMENT("push parmBlk {");
     if (VM_Version::has_Crypto_AES()   ) { __ z_cghi(keylen, 52); }
+    if (VM_Version::has_Crypto_AES128()) { __ z_brl(parmBlk_128); }  // keyLen <  52: AES128
+    if (VM_Version::has_Crypto_AES192()) { __ z_bre(parmBlk_192); }  // keyLen == 52: AES192
     if (VM_Version::has_Crypto_AES256()) { __ z_brh(parmBlk_256); }  // keyLen >  52: AES256
-    if (VM_Version::has_Crypto_AES192()) { __ z_bre(parmBlk_192); }  // keyLen == 52: AES192
-    if (VM_Version::has_Crypto_AES128()) { __ z_brl(parmBlk_128); }  // keyLen <  52: AES128
 
     // Security net: requested AES function not available on this CPU.
     // NOTE:
@@ -1751,71 +1796,35 @@
     //   at all, we have at least AES-128.
     __ stop_static("AES key strength not supported by CPU. Use -XX:-UseAES as remedy.", 0);
 
-    if (VM_Version::has_Crypto_AES128()) {
-      __ bind(parmBlk_128);
-      cv_len  = VM_Version::Cipher::_AES128_dataBlk;
-      key_len = VM_Version::Cipher::_AES128_parmBlk_C - cv_len;
-      __ z_lay(parmBlk, -(VM_Version::Cipher::_AES128_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP);
-      __ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff);  // align parameter block
-
-      // Resize the frame to accommodate for the aligned parameter block and other stuff.
-      // There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk).
-      __ z_stg(keylen, -8, parmBlk);                   // Spill keylen for later use.
-      __ z_stg(Z_SP,  -16, parmBlk);                   // Spill SP for easy revert.
-      __ z_aghi(parmBlk, -AES_parmBlk_addspace);       // Additional space for keylen, etc..
-      __ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP.
-      __ z_aghi(parmBlk,  AES_parmBlk_addspace);       // Restore parameter block address.
-
-      __ z_mvc(0,      cv_len-1,  parmBlk, 0, cv);     // Copy cv.
-      __ z_mvc(cv_len, key_len-1, parmBlk, 0, key);    // Copy key.
-      __ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode);
-      if (VM_Version::has_Crypto_AES192() || VM_Version::has_Crypto_AES256()) {
+    if (VM_Version::has_Crypto_AES256()) {
+      __ bind(parmBlk_256);
+      generate_push_Block(VM_Version::Cipher::_AES256_dataBlk,
+                          VM_Version::Cipher::_AES256_parmBlk_C,
+                          VM_Version::Cipher::_AES256 + mode,
+                          parmBlk, keylen, fCode, cv, key);
+      if (VM_Version::has_Crypto_AES128() || VM_Version::has_Crypto_AES192()) {
         __ z_bru(parmBlk_set);  // Fallthru otherwise.
       }
     }
 
     if (VM_Version::has_Crypto_AES192()) {
       __ bind(parmBlk_192);
-      cv_len  = VM_Version::Cipher::_AES192_dataBlk;
-      key_len = VM_Version::Cipher::_AES192_parmBlk_C - cv_len;
-      __ z_lay(parmBlk, -(VM_Version::Cipher::_AES192_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP);
-      __ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff);  // Align parameter block.
-
-      // Resize the frame to accommodate for the aligned parameter block and other stuff.
-      // There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk).
-      __ z_stg(keylen, -8, parmBlk);                   // Spill keylen for later use.
-      __ z_stg(Z_SP,  -16, parmBlk);                   // Spill SP for easy revert.
-      __ z_aghi(parmBlk, -AES_parmBlk_addspace);       // Additional space for keylen, etc..
-      __ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP.
-      __ z_aghi(parmBlk, AES_parmBlk_addspace);        // Restore parameter block address.
-
-      __ z_mvc(0,      cv_len-1,  parmBlk, 0, cv);     // Copy cv.
-      __ z_mvc(cv_len, key_len-1, parmBlk, 0, key);    // Copy key.
-      __ z_lghi(fCode,    VM_Version::Cipher::_AES192 + mode);
-      if (VM_Version::has_Crypto_AES256()) {
+      generate_push_Block(VM_Version::Cipher::_AES192_dataBlk,
+                          VM_Version::Cipher::_AES192_parmBlk_C,
+                          VM_Version::Cipher::_AES192 + mode,
+                          parmBlk, keylen, fCode, cv, key);
+      if (VM_Version::has_Crypto_AES128()) {
         __ z_bru(parmBlk_set);  // Fallthru otherwise.
       }
     }
 
-    if (VM_Version::has_Crypto_AES256()) {
-      __ bind(parmBlk_256);
-      cv_len  = VM_Version::Cipher::_AES256_dataBlk;
-      key_len = VM_Version::Cipher::_AES256_parmBlk_C - cv_len;
-      __ z_lay(parmBlk, -(VM_Version::Cipher::_AES256_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP);
-      __ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff);  // Align parameter block.
-
-      // Resize the frame to accommodate for the aligned parameter block and other stuff.
-      // There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk).
-      __ z_stg(keylen, -8, parmBlk);                   // Spill keylen for later use.
-      __ z_stg(Z_SP,  -16, parmBlk);                   // Spill SP for easy revert.
-      __ z_aghi(parmBlk, -AES_parmBlk_addspace);       // Additional space for keylen, etc..
-      __ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP.
-      __ z_aghi(parmBlk,  AES_parmBlk_addspace);       // Restore parameter block address.
-
-      __ z_mvc(0,      cv_len-1,  parmBlk, 0, cv);     // Copy cv.
-      __ z_mvc(cv_len, key_len-1, parmBlk, 0, key);    // Copy key.
-      __ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode);
-      // __ z_bru(parmBlk_set);  // fallthru
+    if (VM_Version::has_Crypto_AES128()) {
+      __ bind(parmBlk_128);
+      generate_push_Block(VM_Version::Cipher::_AES128_dataBlk,
+                          VM_Version::Cipher::_AES128_parmBlk_C,
+                          VM_Version::Cipher::_AES128 + mode,
+                          parmBlk, keylen, fCode, cv, key);
+      // Fallthru
     }
 
     __ bind(parmBlk_set);
@@ -1871,41 +1880,49 @@
       }
       __ bind(parmBlk_set);
     }
-    __ z_lg(Z_SP, -16, parmBlk); // Revert resize_frame_absolute.
+    __ z_lg(Z_SP, -16, parmBlk); // Revert resize_frame_absolute. Z_SP saved by push_parmBlk.
     BLOCK_COMMENT("} pop parmBlk");
   }
 
+  // Compute AES encrypt/decrypt function.
+  void generate_AES_cipherBlock(bool is_decipher) {
+    // Incoming arguments.
+    Register       from    = Z_ARG1; // source byte array
+    Register       to      = Z_ARG2; // destination byte array
+    Register       key     = Z_ARG3; // expanded key array
+
+    const Register keylen  = Z_R0;   // Temporarily (until fCode is set) holds the expanded key array length.
+
+    // Register definitions as required by KM instruction.
+    const Register fCode   = Z_R0;   // crypto function code
+    const Register parmBlk = Z_R1;   // parameter block address (points to crypto key)
+    const Register src     = Z_ARG1; // Must be even reg (KM requirement).
+    const Register srclen  = Z_ARG2; // Must be odd reg and pair with src. Overwrites destination address.
+    const Register dst     = Z_ARG3; // Must be even reg (KM requirement). Overwrites expanded key address.
+
+    // Read key len of expanded key (in 4-byte words).
+    __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
+
+    // Copy arguments to registers as required by crypto instruction.
+    __ z_lgr(parmBlk, key);          // crypto key (in T_INT array).
+    __ lgr_if_needed(src, from);     // Copy src address. Will not emit, src/from are identical.
+    __ z_lgr(dst, to);               // Copy dst address, even register required.
+
+    // Construct function code into fCode(Z_R0), data block length into srclen(Z_ARG2).
+    generate_load_AES_fCode(keylen, fCode, srclen, is_decipher);
+
+    __ km(dst, src);                 // Cipher the message.
+
+    __ z_br(Z_R14);
+  }
+
   // Compute AES encrypt function.
   address generate_AES_encryptBlock(const char* name) {
     __ align(CodeEntryAlignment);
     StubCodeMark mark(this, "StubRoutines", name);
-    unsigned int   start_off = __ offset();  // Remember stub start address (is rtn value).
-
-    Register       from    = Z_ARG1; // source byte array
-    Register       to      = Z_ARG2; // destination byte array
-    Register       key     = Z_ARG3; // expanded key array
-
-    const Register keylen  = Z_R0;   // Temporarily (until fCode is set) holds the expanded key array length.
-    const Register fCode   = Z_R0;   // crypto function code
-    const Register parmBlk = Z_R1;   // parameter block address (points to crypto key)
-    const Register src     = Z_ARG1; // is Z_R2
-    const Register srclen  = Z_ARG2; // Overwrites destination address.
-    const Register dst     = Z_ARG3; // Overwrites expanded key address.
-
-    // Read key len of expanded key (in 4-byte words).
-    __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
-
-    // Copy arguments to registers as required by crypto instruction.
-    __ z_lgr(parmBlk, key);          // crypto key (in T_INT array).
-    // __ z_lgr(src, from);          // Copy not needed, src/from are identical.
-    __ z_lgr(dst, to);               // Copy destination address to even register.
-
-    // Construct function code in Z_R0, data block length in Z_ARG2.
-    generate_load_AES_fCode(keylen, fCode, srclen, false);
-
-    __ km(dst, src);          // Cipher the message.
-
-    __ z_br(Z_R14);
+    unsigned int start_off = __ offset();  // Remember stub start address (is rtn value).
+
+    generate_AES_cipherBlock(false);
 
     return __ addr_at(start_off);
   }
@@ -1914,33 +1931,9 @@
   address generate_AES_decryptBlock(const char* name) {
     __ align(CodeEntryAlignment);
     StubCodeMark mark(this, "StubRoutines", name);
-    unsigned int   start_off = __ offset();  // Remember stub start address (is rtn value).
-
-    Register       from    = Z_ARG1; // source byte array
-    Register       to      = Z_ARG2; // destination byte array
-    Register       key     = Z_ARG3; // expanded key array, not preset at entry!!!
-
-    const Register keylen  = Z_R0;   // Temporarily (until fCode is set) holds the expanded key array length.
-    const Register fCode   = Z_R0;   // crypto function code
-    const Register parmBlk = Z_R1;   // parameter block address (points to crypto key)
-    const Register src     = Z_ARG1; // is Z_R2
-    const Register srclen  = Z_ARG2; // Overwrites destination address.
-    const Register dst     = Z_ARG3; // Overwrites key address.
-
-    // Read key len of expanded key (in 4-byte words).
-    __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
-
-    // Copy arguments to registers as required by crypto instruction.
-    __ z_lgr(parmBlk, key);     // Copy crypto key address.
-    // __ z_lgr(src, from);     // Copy not needed, src/from are identical.
-    __ z_lgr(dst, to);          // Copy destination address to even register.
-
-    // Construct function code in Z_R0, data block length in Z_ARG2.
-    generate_load_AES_fCode(keylen, fCode, srclen, true);
-
-    __ km(dst, src);          // Cipher the message.
-
-    __ z_br(Z_R14);
+    unsigned int start_off = __ offset();  // Remember stub start address (is rtn value).
+
+    generate_AES_cipherBlock(true);
 
     return __ addr_at(start_off);
   }
@@ -1958,10 +1951,7 @@
   // We align the parameter block to the next available octoword.
   //
   // Compute chained AES encrypt function.
-  address generate_cipherBlockChaining_AES_encrypt(const char* name) {
-    __ align(CodeEntryAlignment);
-    StubCodeMark mark(this, "StubRoutines", name);
-    unsigned int   start_off = __ offset();  // Remember stub start address (is rtn value).
+  void generate_AES_cipherBlockChaining(bool is_decipher) {
 
     Register       from    = Z_ARG1; // source byte array (clear text)
     Register       to      = Z_ARG2; // destination byte array (ciphered)
@@ -1981,20 +1971,29 @@
     __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
 
     // Construct parm block address in parmBlk (== Z_R1), copy cv and key to parm block.
-    // Construct function code in Z_R0.
-    generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, false);
+    // Construct function code in fCode (Z_R0).
+    generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, is_decipher);
 
     // Prepare other registers for instruction.
-    // __ z_lgr(src, from);     // Not needed, registers are the same.
+    __ lgr_if_needed(src, from);     // Copy src address. Will not emit, src/from are identical.
     __ z_lgr(dst, to);
-    __ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required.
-
-    __ kmc(dst, src);           // Cipher the message.
+    __ z_llgfr(srclen, msglen);      // We pass the offsets as ints, not as longs as required.
+
+    __ kmc(dst, src);                // Cipher the message.
 
     generate_pop_parmBlk(keylen, parmBlk, key, cv);
 
-    __ z_llgfr(Z_RET, msglen);  // We pass the offsets as ints, not as longs as required.
+    __ z_llgfr(Z_RET, msglen);       // We pass the offsets as ints, not as longs as required.
     __ z_br(Z_R14);
+  }
+
+  // Compute chained AES encrypt function.
+  address generate_cipherBlockChaining_AES_encrypt(const char* name) {
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", name);
+    unsigned int   start_off = __ offset();  // Remember stub start address (is rtn value).
+
+    generate_AES_cipherBlockChaining(false);
 
     return __ addr_at(start_off);
   }
@@ -2005,38 +2004,7 @@
     StubCodeMark mark(this, "StubRoutines", name);
     unsigned int   start_off = __ offset();  // Remember stub start address (is rtn value).
 
-    Register       from    = Z_ARG1; // source byte array (ciphered)
-    Register       to      = Z_ARG2; // destination byte array (clear text)
-    Register       key     = Z_ARG3; // expanded key array, not preset at entry!!!
-    Register       cv      = Z_ARG4; // chaining value
-    const Register msglen  = Z_ARG5; // Total length of the msg to be encrypted. Value must be returned
-                                     // in Z_RET upon completion of this stub.
-
-    const Register keylen  = Z_R0;   // Expanded key length, as read from key array. Temp only.
-    const Register fCode   = Z_R0;   // crypto function code
-    const Register parmBlk = Z_R1;   // parameter block address (points to crypto key)
-    const Register src     = Z_ARG1; // is Z_R2
-    const Register srclen  = Z_ARG2; // Overwrites destination address.
-    const Register dst     = Z_ARG3; // Overwrites key address.
-
-    // Read key len of expanded key (in 4-byte words).
-    __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
-
-    // Construct parm block address in parmBlk (== Z_R1), copy cv and key to parm block.
-    // Construct function code in Z_R0.
-    generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, true);
-
-    // Prepare other registers for instruction.
-    // __ z_lgr(src, from);     // Not needed, registers are the same.
-    __ z_lgr(dst, to);
-    __ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required.
-
-    __ kmc(dst, src);           // Decipher the message.
-
-    generate_pop_parmBlk(keylen, parmBlk, key, cv);
-
-    __ z_llgfr(Z_RET, msglen);  // We pass the offsets as ints, not as longs as required.
-    __ z_br(Z_R14);
+    generate_AES_cipherBlockChaining(true);
 
     return __ addr_at(start_off);
   }
--- a/src/cpu/s390/vm/vm_version_s390.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/s390/vm/vm_version_s390.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2017 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
@@ -153,6 +153,10 @@
     warning("AES intrinsics are not available on this CPU");
     FLAG_SET_DEFAULT(UseAESIntrinsics, false);
   }
+  if (UseAESIntrinsics && !UseAES) {
+    warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
+    FLAG_SET_DEFAULT(UseAESIntrinsics, false);
+  }
 
   // TODO: implement AES/CTR intrinsics
   if (UseAESCTRIntrinsics) {
--- a/src/cpu/sparc/vm/c2_globals_sparc.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -53,7 +53,6 @@
 define_pd_global(bool, ResizeTLAB,                   true);
 define_pd_global(intx, LoopUnrollLimit,              60); // Design center runs on 1.3.1
 define_pd_global(intx, LoopPercentProfileLimit,      10);
-define_pd_global(intx, PostLoopMultiversioning,      false);
 define_pd_global(intx, MinJumpTableSize,             5);
 
 // Peephole and CISC spilling both break the graph, and so makes the
--- a/src/cpu/sparc/vm/sparc.ad	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/sparc/vm/sparc.ad	Wed Aug 02 15:59:33 2017 +0000
@@ -3182,6 +3182,16 @@
   interface(CONST_INTER);
 %}
 
+// Unsigned Long Immediate: 12-bit (non-negative that fits in simm13)
+operand immUL12() %{
+  predicate((0 <= n->get_long()) && (n->get_long() == (int)n->get_long()) && Assembler::is_simm13((int)n->get_long()));
+  match(ConL);
+  op_cost(0);
+
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
 // Integer Immediate non-negative
 operand immU31()
 %{
@@ -3709,6 +3719,15 @@
   interface(REG_INTER);
 %}
 
+// Condition Code Register, unsigned long comparisons.
+operand flagsRegUL() %{
+  constraint(ALLOC_IN_RC(int_flags));
+  match(RegFlags);
+
+  format %{ "xcc_UL" %}
+  interface(REG_INTER);
+%}
+
 // Condition Code Register, floating comparisons, unordered same as "less".
 operand flagsRegF() %{
   constraint(ALLOC_IN_RC(float_flags));
@@ -8416,6 +8435,17 @@
   ins_pipe(ialu_cconly_reg_reg);
 %}
 
+instruct compUL_iReg(flagsRegUL xcc, iRegL op1, iRegL op2) %{
+  match(Set xcc (CmpUL op1 op2));
+  effect(DEF xcc, USE op1, USE op2);
+
+  size(4);
+  format %{ "CMP    $op1,$op2\t! unsigned long" %}
+  opcode(Assembler::subcc_op3, Assembler::arith_op);
+  ins_encode(form3_rs1_rs2_rd(op1, op2, R_G0));
+  ins_pipe(ialu_cconly_reg_reg);
+%}
+
 instruct compI_iReg_imm13(flagsReg icc, iRegI op1, immI13 op2) %{
   match(Set icc (CmpI op1 op2));
   effect( DEF icc, USE op1 );
@@ -8502,6 +8532,17 @@
   ins_pipe(ialu_cconly_reg_imm);
 %}
 
+instruct compUL_iReg_imm13(flagsRegUL xcc, iRegL op1, immUL12 op2) %{
+  match(Set xcc (CmpUL op1 op2));
+  effect(DEF xcc, USE op1, USE op2);
+
+  size(4);
+  format %{ "CMP    $op1,$op2\t! unsigned long" %}
+  opcode(Assembler::subcc_op3, Assembler::arith_op);
+  ins_encode(form3_rs1_simm13_rd(op1, op2, R_G0));
+  ins_pipe(ialu_cconly_reg_imm);
+%}
+
 // Compare Pointers
 instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
   match(Set pcc (CmpP op1 op2));
@@ -8875,6 +8916,44 @@
   ins_pipe(cmp_br_reg_imm);
 %}
 
+instruct cmpUL_reg_branch(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{
+  match(If cmp (CmpUL op1 op2));
+  effect(USE labl, KILL xcc);
+
+  size(12);
+  ins_cost(BRANCH_COST);
+  format %{ "CMP    $op1,$op2\t! unsigned long\n\t"
+            "BP$cmp   $labl" %}
+  ins_encode %{
+    Label* L = $labl$$label;
+    Assembler::Predict predict_taken =
+      cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
+    __ cmp($op1$$Register, $op2$$Register);
+    __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
+    __ delayed()->nop();
+  %}
+  ins_pipe(cmp_br_reg_reg);
+%}
+
+instruct cmpUL_imm_branch(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{
+  match(If cmp (CmpUL op1 op2));
+  effect(USE labl, KILL xcc);
+
+  size(12);
+  ins_cost(BRANCH_COST);
+  format %{ "CMP    $op1,$op2\t! unsigned long\n\t"
+            "BP$cmp   $labl" %}
+  ins_encode %{
+    Label* L = $labl$$label;
+    Assembler::Predict predict_taken =
+      cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
+    __ cmp($op1$$Register, $op2$$constant);
+    __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
+    __ delayed()->nop();
+  %}
+  ins_pipe(cmp_br_reg_imm);
+%}
+
 instruct cmpL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{
   match(If cmp (CmpL op1 op2));
   effect(USE labl, KILL xcc);
@@ -9103,6 +9182,42 @@
   ins_pipe(cbcond_reg_imm);
 %}
 
+instruct cmpUL_reg_branch_short(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{
+  match(If cmp (CmpUL op1 op2));
+  predicate(UseCBCond);
+  effect(USE labl, KILL xcc);
+
+  size(4);
+  ins_cost(BRANCH_COST);
+  format %{ "CXB$cmp  $op1,$op2,$labl\t! unsigned long" %}
+  ins_encode %{
+    Label* L = $labl$$label;
+    assert(__ use_cbcond(*L), "back to back cbcond");
+    __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$Register, *L);
+  %}
+  ins_short_branch(1);
+  ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER);
+  ins_pipe(cbcond_reg_reg);
+%}
+
+instruct cmpUL_imm_branch_short(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{
+  match(If cmp (CmpUL op1 op2));
+  predicate(UseCBCond);
+  effect(USE labl, KILL xcc);
+
+  size(4);
+  ins_cost(BRANCH_COST);
+  format %{ "CXB$cmp  $op1,$op2,$labl\t! unsigned long" %}
+  ins_encode %{
+    Label* L = $labl$$label;
+    assert(__ use_cbcond(*L), "back to back cbcond");
+    __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$constant, *L);
+  %}
+  ins_short_branch(1);
+  ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER);
+  ins_pipe(cbcond_reg_imm);
+%}
+
 instruct cmpL_reg_branch_short(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{
   match(If cmp (CmpL op1 op2));
   predicate(UseCBCond);
@@ -9333,6 +9448,25 @@
   ins_pipe(br_cc);
 %}
 
+instruct branchConU_long(cmpOpU cmp, flagsRegUL xcc, label labl) %{
+  match(If cmp xcc);
+  effect(USE labl);
+
+  size(8);
+  ins_cost(BRANCH_COST);
+  format %{ "BP$cmp   $xcc,$labl" %}
+  ins_encode %{
+    Label* L = $labl$$label;
+    Assembler::Predict predict_taken =
+      cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
+
+    __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
+    __ delayed()->nop();
+  %}
+  ins_avoid_back_to_back(AVOID_BEFORE);
+  ins_pipe(br_cc);
+%}
+
 // Manifest a CmpL3 result in an integer register.  Very painful.
 // This is the test to avoid.
 instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
--- a/src/cpu/x86/vm/c2_globals_x86.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/x86/vm/c2_globals_x86.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -47,7 +47,6 @@
 define_pd_global(intx, FreqInlineSize,               325);
 define_pd_global(intx, MinJumpTableSize,             10);
 define_pd_global(intx, LoopPercentProfileLimit,      30);
-define_pd_global(intx, PostLoopMultiversioning,      true);
 #ifdef AMD64
 define_pd_global(intx, INTPRESSURE,                  13);
 define_pd_global(intx, FLOATPRESSURE,                14);
--- a/src/cpu/x86/vm/globals_x86.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/x86/vm/globals_x86.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -116,7 +116,7 @@
   product(bool, UseStoreImmI16, true,                                       \
           "Use store immediate 16-bits value instruction on x86")           \
                                                                             \
-  product(intx, UseAVX, 99,                                                 \
+  product(intx, UseAVX, 2,                                                  \
           "Highest supported AVX instructions set on x86/x64")              \
           range(0, 99)                                                      \
                                                                             \
--- a/src/cpu/x86/vm/x86_32.ad	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/x86/vm/x86_32.ad	Wed Aug 02 15:59:33 2017 +0000
@@ -4027,6 +4027,26 @@
   interface(REG_INTER);
 %}
 
+// Condition Code Register used by unsigned long compare
+operand flagsReg_ulong_LTGE() %{
+  constraint(ALLOC_IN_RC(int_flags));
+  match(RegFlags);
+  format %{ "FLAGS_U_LTGE" %}
+  interface(REG_INTER);
+%}
+operand flagsReg_ulong_EQNE() %{
+  constraint(ALLOC_IN_RC(int_flags));
+  match(RegFlags);
+  format %{ "FLAGS_U_EQNE" %}
+  interface(REG_INTER);
+%}
+operand flagsReg_ulong_LEGT() %{
+  constraint(ALLOC_IN_RC(int_flags));
+  match(RegFlags);
+  format %{ "FLAGS_U_LEGT" %}
+  interface(REG_INTER);
+%}
+
 // Float register operands
 operand regDPR() %{
   predicate( UseSSE < 2 );
@@ -4585,7 +4605,7 @@
   %}
 %}
 
-// Comparision Code used in long compares
+// Comparison Code used in long compares
 operand cmpOp_commute() %{
   match(Bool);
 
@@ -4602,6 +4622,23 @@
   %}
 %}
 
+// Comparison Code used in unsigned long compares
+operand cmpOpU_commute() %{
+  match(Bool);
+
+  format %{ "" %}
+  interface(COND_INTER) %{
+    equal(0x4, "e");
+    not_equal(0x5, "ne");
+    less(0x7, "nbe");
+    greater_equal(0x6, "be");
+    less_equal(0x3, "nb");
+    greater(0x2, "b");
+    overflow(0x0, "o");
+    no_overflow(0x1, "no");
+  %}
+%}
+
 //----------OPERAND CLASSES----------------------------------------------------
 // Operand Classes are groups of operands that are used as to simplify
 // instruction definitions by not requiring the AD writer to specify separate
@@ -12636,6 +12673,44 @@
   %}
 %}
 
+//======
+// Manifest a CmpUL result in the normal flags.  Only good for LT or GE
+// compares.  Can be used for LE or GT compares by reversing arguments.
+// NOT GOOD FOR EQ/NE tests.
+instruct cmpUL_zero_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src, immL0 zero) %{
+  match(Set flags (CmpUL src zero));
+  ins_cost(100);
+  format %{ "TEST   $src.hi,$src.hi" %}
+  opcode(0x85);
+  ins_encode(OpcP, RegReg_Hi2(src, src));
+  ins_pipe(ialu_cr_reg_reg);
+%}
+
+// Manifest a CmpUL result in the normal flags.  Only good for LT or GE
+// compares.  Can be used for LE or GT compares by reversing arguments.
+// NOT GOOD FOR EQ/NE tests.
+instruct cmpUL_reg_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src1, eRegL src2, rRegI tmp) %{
+  match(Set flags (CmpUL src1 src2));
+  effect(TEMP tmp);
+  ins_cost(300);
+  format %{ "CMP    $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
+            "MOV    $tmp,$src1.hi\n\t"
+            "SBB    $tmp,$src2.hi\t! Compute flags for unsigned long compare" %}
+  ins_encode(long_cmp_flags2(src1, src2, tmp));
+  ins_pipe(ialu_cr_reg_reg);
+%}
+
+// Unsigned long compares reg < zero/req OR reg >= zero/req.
+// Just a wrapper for a normal branch, plus the predicate test.
+instruct cmpUL_LTGE(cmpOpU cmp, flagsReg_ulong_LTGE flags, label labl) %{
+  match(If cmp flags);
+  effect(USE labl);
+  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
+  expand %{
+    jmpCon(cmp, flags, labl);    // JLT or JGE...
+  %}
+%}
+
 // Compare 2 longs and CMOVE longs.
 instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{
   match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
@@ -12764,6 +12839,41 @@
   %}
 %}
 
+//======
+// Manifest a CmpUL result in the normal flags.  Only good for EQ/NE compares.
+instruct cmpUL_zero_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src, immL0 zero, rRegI tmp) %{
+  match(Set flags (CmpUL src zero));
+  effect(TEMP tmp);
+  ins_cost(200);
+  format %{ "MOV    $tmp,$src.lo\n\t"
+            "OR     $tmp,$src.hi\t! Unsigned long is EQ/NE 0?" %}
+  ins_encode(long_cmp_flags0(src, tmp));
+  ins_pipe(ialu_reg_reg_long);
+%}
+
+// Manifest a CmpUL result in the normal flags.  Only good for EQ/NE compares.
+instruct cmpUL_reg_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src1, eRegL src2) %{
+  match(Set flags (CmpUL src1 src2));
+  ins_cost(200+300);
+  format %{ "CMP    $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
+            "JNE,s  skip\n\t"
+            "CMP    $src1.hi,$src2.hi\n\t"
+     "skip:\t" %}
+  ins_encode(long_cmp_flags1(src1, src2));
+  ins_pipe(ialu_cr_reg_reg);
+%}
+
+// Unsigned long compare reg == zero/reg OR reg != zero/reg
+// Just a wrapper for a normal branch, plus the predicate test.
+instruct cmpUL_EQNE(cmpOpU cmp, flagsReg_ulong_EQNE flags, label labl) %{
+  match(If cmp flags);
+  effect(USE labl);
+  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
+  expand %{
+    jmpCon(cmp, flags, labl);    // JEQ or JNE...
+  %}
+%}
+
 // Compare 2 longs and CMOVE longs.
 instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{
   match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
@@ -12897,6 +13007,46 @@
   %}
 %}
 
+//======
+// Manifest a CmpUL result in the normal flags.  Only good for LE or GT compares.
+// Same as cmpUL_reg_flags_LEGT except must negate src
+instruct cmpUL_zero_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src, immL0 zero, rRegI tmp) %{
+  match(Set flags (CmpUL src zero));
+  effect(TEMP tmp);
+  ins_cost(300);
+  format %{ "XOR    $tmp,$tmp\t# Unsigned long compare for -$src < 0, use commuted test\n\t"
+            "CMP    $tmp,$src.lo\n\t"
+            "SBB    $tmp,$src.hi\n\t" %}
+  ins_encode(long_cmp_flags3(src, tmp));
+  ins_pipe(ialu_reg_reg_long);
+%}
+
+// Manifest a CmpUL result in the normal flags.  Only good for LE or GT compares.
+// Same as cmpUL_reg_flags_LTGE except operands swapped.  Swapping operands
+// requires a commuted test to get the same result.
+instruct cmpUL_reg_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src1, eRegL src2, rRegI tmp) %{
+  match(Set flags (CmpUL src1 src2));
+  effect(TEMP tmp);
+  ins_cost(300);
+  format %{ "CMP    $src2.lo,$src1.lo\t! Unsigned long compare, swapped operands, use with commuted test\n\t"
+            "MOV    $tmp,$src2.hi\n\t"
+            "SBB    $tmp,$src1.hi\t! Compute flags for unsigned long compare" %}
+  ins_encode(long_cmp_flags2( src2, src1, tmp));
+  ins_pipe(ialu_cr_reg_reg);
+%}
+
+// Unsigned long compares reg < zero/req OR reg >= zero/req.
+// Just a wrapper for a normal branch, plus the predicate test
+instruct cmpUL_LEGT(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, label labl) %{
+  match(If cmp flags);
+  effect(USE labl);
+  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
+  ins_cost(300);
+  expand %{
+    jmpCon(cmp, flags, labl);    // JGT or JLE...
+  %}
+%}
+
 // Compare 2 longs and CMOVE longs.
 instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{
   match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
--- a/src/cpu/x86/vm/x86_64.ad	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/cpu/x86/vm/x86_64.ad	Wed Aug 02 15:59:33 2017 +0000
@@ -11515,6 +11515,48 @@
   ins_pipe(pipe_slow);
 %}
 
+// Unsigned long compare Instructions; really, same as signed long except they
+// produce an rFlagsRegU instead of rFlagsReg.
+instruct compUL_rReg(rFlagsRegU cr, rRegL op1, rRegL op2)
+%{
+  match(Set cr (CmpUL op1 op2));
+
+  format %{ "cmpq    $op1, $op2\t# unsigned" %}
+  opcode(0x3B);  /* Opcode 3B /r */
+  ins_encode(REX_reg_reg_wide(op1, op2), OpcP, reg_reg(op1, op2));
+  ins_pipe(ialu_cr_reg_reg);
+%}
+
+instruct compUL_rReg_imm(rFlagsRegU cr, rRegL op1, immL32 op2)
+%{
+  match(Set cr (CmpUL op1 op2));
+
+  format %{ "cmpq    $op1, $op2\t# unsigned" %}
+  opcode(0x81, 0x07); /* Opcode 81 /7 */
+  ins_encode(OpcSErm_wide(op1, op2), Con8or32(op2));
+  ins_pipe(ialu_cr_reg_imm);
+%}
+
+instruct compUL_rReg_mem(rFlagsRegU cr, rRegL op1, memory op2)
+%{
+  match(Set cr (CmpUL op1 (LoadL op2)));
+
+  format %{ "cmpq    $op1, $op2\t# unsigned" %}
+  opcode(0x3B); /* Opcode 3B /r */
+  ins_encode(REX_reg_mem_wide(op1, op2), OpcP, reg_mem(op1, op2));
+  ins_pipe(ialu_cr_reg_mem);
+%}
+
+instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero)
+%{
+  match(Set cr (CmpUL src zero));
+
+  format %{ "testq   $src, $src\t# unsigned" %}
+  opcode(0x85);
+  ins_encode(REX_reg_reg_wide(src, src), OpcP, reg_reg(src, src));
+  ins_pipe(ialu_cr_reg_imm);
+%}
+
 //----------Max and Min--------------------------------------------------------
 // Min Instructions
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java	Wed Aug 02 15:59:33 2017 +0000
@@ -138,6 +138,8 @@
                 if (build >= JVMCI9_MIN_EA_BUILD) {
                     return;
                 }
+                // Using Object.equals suppresses Eclipse's "Dead code" warning.
+                // Unfortunately @SuppressWarnings("unused") can only be applied at method level.
                 if (Objects.equals(JVMCI9_MIN_EA_BUILD, Integer.MAX_VALUE)) {
                     failVersionCheck(exitOnFailure, "This version of Graal is not compatible with any JDK 9 Early Access build.%n");
                 } else {
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il	Wed Aug 02 08:53:18 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-//
-// Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
-// 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.
-//
-//
-
-
-  // Support for u8 os::setup_fpu()
-      .inline _solaris_raw_setup_fpu,1
-      movl     0(%esp), %eax
-      fldcw    (%eax)
-      .end
-
-  // The argument size of each inline directive is ignored by the compiler
-  // and is set to 0 for compatibility reason.
-
-  // Get the raw thread ID from %gs:0
-      .inline _raw_thread_id,0
-      movl     %gs:0, %eax
-      .end
-
-  // Get current sp
-      .inline _get_current_sp,0
-      .volatile
-      movl     %esp, %eax
-      .end
-
-  // Get current fp
-      .inline _get_current_fp,0
-      .volatile
-      movl     %ebp, %eax
-      .end
-
-  // Support for os::rdtsc()
-      .inline _raw_rdtsc,0
-      rdtsc
-      .end
-
-  // Support for jint Atomic::add(jint inc, volatile jint* dest)
-      .inline _Atomic_add,3
-      movl     0(%esp), %eax   // inc
-      movl     4(%esp), %edx   // dest
-      movl     %eax, %ecx
-      lock xaddl %eax, (%edx)
-      addl     %ecx, %eax
-      .end
-
-  // Support for jint Atomic::xchg(jint exchange_value, volatile jint* dest).
-      .inline _Atomic_xchg,2
-      movl     0(%esp), %eax   // exchange_value
-      movl     4(%esp), %ecx   // dest
-      xchgl    (%ecx), %eax
-      .end
-
-  // Support for jbyte Atomic::cmpxchg(jbyte exchange_value,
-  //                                   volatile jbyte *dest,
-  //                                   jbyte compare_value)
-      .inline _Atomic_cmpxchg_byte,4
-      movb     8(%esp), %al   // compare_value
-      movb     0(%esp), %cl   // exchange_value
-      movl     4(%esp), %edx   // dest
-      lock cmpxchgb %cl, (%edx)
-      .end
-
-  // Support for jint Atomic::cmpxchg(jint exchange_value,
-  //                                  volatile jint *dest,
-  //                                  jint compare_value)
-      .inline _Atomic_cmpxchg,4
-      movl     8(%esp), %eax   // compare_value
-      movl     0(%esp), %ecx   // exchange_value
-      movl     4(%esp), %edx   // dest
-      lock cmpxchgl %ecx, (%edx)
-      .end
-
-  // Support for jlong Atomic::cmpxchg(jlong exchange_value,
-  //                                   volatile jlong* dest,
-  //                                   jlong compare_value)
-      .inline _Atomic_cmpxchg_long,6
-      pushl    %ebx
-      pushl    %edi
-      movl     20(%esp), %eax  // compare_value (low)
-      movl     24(%esp), %edx  // compare_value (high)
-      movl     16(%esp), %edi  // dest
-      movl     8(%esp), %ebx   // exchange_value (low)
-      movl     12(%esp), %ecx  // exchange_high (high)
-      lock cmpxchg8b (%edi)
-      popl     %edi
-      popl     %ebx
-      .end
-
-  // Support for jlong Atomic::load and Atomic::store.
-  // void _Atomic_move_long(const volatile jlong* src, volatile jlong* dst)
-      .inline _Atomic_move_long,2
-      movl     0(%esp), %eax   // src
-      fildll    (%eax)
-      movl     4(%esp), %eax   // dest
-      fistpll   (%eax)
-      .end
-
-  // Support for u2 Bytes::swap_u2(u2 x)
-      .inline _raw_swap_u2,1
-      movl     0(%esp), %eax
-      xchgb    %al, %ah
-      .end
-
-  // Support for u4 Bytes::swap_u4(u4 x)
-      .inline _raw_swap_u4,1
-      movl     0(%esp), %eax
-      bswap    %eax
-      .end
-
-  // Support for u8 Bytes::swap_u8_base(u4 x, u4 y)
-      .inline _raw_swap_u8,2
-      movl     4(%esp), %eax   // y
-      movl     0(%esp), %edx   // x
-      bswap    %eax
-      bswap    %edx
-      .end
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.s	Wed Aug 02 08:53:18 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,661 +0,0 @@
-//
-// Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
-// 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.
-//
-
-	.globl fixcw
-	.globl sse_check
-	.globl sse_unavailable
-	.globl gs_load
-	.globl gs_thread
-        .globl _Atomic_cmpxchg_long_gcc
-
-        // NOTE WELL!  The _Copy functions are called directly
-	// from server-compiler-generated code via CallLeafNoFP,
-	// which means that they *must* either not use floating
-	// point or use it in the same manner as does the server
-	// compiler.
-
-        .globl _Copy_conjoint_bytes
-        .globl _Copy_arrayof_conjoint_bytes
-        .globl _Copy_conjoint_jshorts_atomic
-	.globl _Copy_arrayof_conjoint_jshorts
-        .globl _Copy_conjoint_jints_atomic
-        .globl _Copy_arrayof_conjoint_jints
-	.globl _Copy_conjoint_jlongs_atomic
-        .globl _mmx_Copy_arrayof_conjoint_jshorts
-
-	.section .text,"ax"
-
-/ Support for void os::Solaris::init_thread_fpu_state() in os_solaris_i486.cpp
-/ Set fpu to 53 bit precision.  This happens too early to use a stub.
-	.align   16
-fixcw:
-	pushl    $0x27f
-	fldcw    0(%esp)
-	popl     %eax
-	ret
-
-        .align  16
-        .globl  SpinPause
-SpinPause:
-        rep 
-        nop
-        movl    $1, %eax
-        ret
-
-
-/ Test SSE availability, used by os_solaris_i486.cpp
-	.align   16
-sse_check:
-	/ Fault if SSE not available
-	xorps %xmm0,%xmm0
-	/ No fault
-	movl $1,%eax
-	ret
-	/ Signal handler continues here if SSE is not available
-sse_unavailable:
-	xorl %eax,%eax
-	ret
-
-/ Fast thread accessors, used by threadLS_solaris_i486.cpp
-	.align   16
-gs_load:
-	movl 4(%esp),%ecx
-	movl %gs:(%ecx),%eax
-	ret
-
-	.align   16
-gs_thread:
-	movl %gs:0x0,%eax
-	ret
-
-        / Support for void Copy::conjoint_bytes(void* from,
-        /                                       void* to,
-        /                                       size_t count)
-        .align   16
-_Copy_conjoint_bytes:
-        pushl    %esi
-        movl     4+12(%esp),%ecx      / count
-        pushl    %edi
-        movl     8+ 4(%esp),%esi      / from
-        movl     8+ 8(%esp),%edi      / to
-        cmpl     %esi,%edi
-        leal     -1(%esi,%ecx),%eax   / from + count - 1
-        jbe      cb_CopyRight
-        cmpl     %eax,%edi
-        jbe      cb_CopyLeft
-        / copy from low to high
-cb_CopyRight:
-        cmpl     $3,%ecx
-        jbe      5f                   / <= 3 bytes
-        / align source address at dword address boundary
-        movl     %ecx,%eax            / original count
-        movl     $4,%ecx
-        subl     %esi,%ecx
-        andl     $3,%ecx              / prefix byte count
-        jz       1f                   / no prefix
-        subl     %ecx,%eax            / byte count less prefix
-        / copy prefix
-        subl     %esi,%edi
-0:      movb     (%esi),%dl
-        movb     %dl,(%edi,%esi,1)
-        addl     $1,%esi
-        subl     $1,%ecx
-        jnz      0b
-        addl     %esi,%edi
-1:      movl     %eax,%ecx            / byte count less prefix
-        shrl     $2,%ecx              / dword count
-        jz       4f                   / no dwords to move
-        cmpl     $32,%ecx
-        jbe      2f                   / <= 32 dwords
-        / copy aligned dwords
-        rep;     smovl
-        jmp      4f
-        / copy aligned dwords
-2:      subl     %esi,%edi
-        .align   16
-3:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        addl     $4,%esi
-        subl     $1,%ecx
-        jnz      3b
-        addl     %esi,%edi
-4:      movl     %eax,%ecx            / byte count less prefix
-5:      andl     $3,%ecx              / suffix byte count
-        jz       7f                   / no suffix
-        / copy suffix
-        xorl     %eax,%eax
-6:      movb     (%esi,%eax,1),%dl
-        movb     %dl,(%edi,%eax,1)
-        addl     $1,%eax
-        subl     $1,%ecx
-        jnz      6b
-7:      popl     %edi
-        popl     %esi
-        ret
-        / copy from high to low
-cb_CopyLeft:
-        std
-        leal     -4(%edi,%ecx),%edi   / to + count - 4
-        movl     %eax,%esi            / from + count - 1
-        movl     %ecx,%eax
-        subl     $3,%esi              / from + count - 4
-        cmpl     $3,%ecx
-        jbe      5f                   / <= 3 bytes
-1:      shrl     $2,%ecx              / dword count
-        jz       4f                   / no dwords to move
-        cmpl     $32,%ecx
-        ja       3f                   / > 32 dwords
-        / copy dwords, aligned or not
-        subl     %esi,%edi
-        .align   16
-2:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        subl     $4,%esi
-        subl     $1,%ecx
-        jnz      2b
-        addl     %esi,%edi
-        jmp      4f
-        / copy dwords, aligned or not
-3:      rep;     smovl
-4:      movl     %eax,%ecx            / byte count
-5:      andl     $3,%ecx              / suffix byte count
-        jz       7f                   / no suffix
-        / copy suffix
-        subl     %esi,%edi
-        addl     $3,%esi
-6:      movb     (%esi),%dl
-        movb     %dl,(%edi,%esi,1)
-	subl     $1,%esi
-        subl     $1,%ecx
-        jnz      6b
-7:      cld
-        popl     %edi
-        popl     %esi
-        ret
-
-        / Support for void Copy::arrayof_conjoint_bytes(void* from,
-        /                                               void* to,
-        /                                               size_t count)
-        /
-        / Same as _Copy_conjoint_bytes, except no source alignment check.
-        .align   16
-_Copy_arrayof_conjoint_bytes:
-        pushl    %esi
-        movl     4+12(%esp),%ecx      / count
-        pushl    %edi
-        movl     8+ 4(%esp),%esi      / from
-        movl     8+ 8(%esp),%edi      / to
-        cmpl     %esi,%edi
-        leal     -1(%esi,%ecx),%eax   / from + count - 1
-        jbe      acb_CopyRight
-        cmpl     %eax,%edi
-        jbe      acb_CopyLeft 
-        / copy from low to high
-acb_CopyRight:
-        cmpl     $3,%ecx
-        jbe      5f
-1:      movl     %ecx,%eax
-        shrl     $2,%ecx
-        jz       4f
-        cmpl     $32,%ecx
-        ja       3f
-        / copy aligned dwords
-        subl     %esi,%edi
-        .align   16
-2:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        addl     $4,%esi
-        subl     $1,%ecx
-        jnz      2b
-        addl     %esi,%edi
-        jmp      4f
-        / copy aligned dwords
-3:      rep;     smovl
-4:      movl     %eax,%ecx
-5:      andl     $3,%ecx
-        jz       7f
-        / copy suffix
-        xorl     %eax,%eax
-6:      movb     (%esi,%eax,1),%dl
-        movb     %dl,(%edi,%eax,1)
-        addl     $1,%eax
-        subl     $1,%ecx
-        jnz      6b
-7:      popl     %edi
-        popl     %esi
-        ret
-acb_CopyLeft:
-        std
-        leal     -4(%edi,%ecx),%edi   / to + count - 4
-        movl     %eax,%esi            / from + count - 1
-        movl     %ecx,%eax
-        subl     $3,%esi              / from + count - 4
-        cmpl     $3,%ecx
-        jbe      5f
-1:      shrl     $2,%ecx
-        jz       4f
-        cmpl     $32,%ecx
-        jbe      2f                   / <= 32 dwords
-        rep;     smovl
-        jmp      4f
-	.=.+8
-2:      subl     %esi,%edi
-        .align   16
-3:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        subl     $4,%esi
-        subl     $1,%ecx
-        jnz      3b
-        addl     %esi,%edi
-4:      movl     %eax,%ecx
-5:      andl     $3,%ecx
-        jz       7f
-        subl     %esi,%edi
-        addl     $3,%esi
-6:      movb     (%esi),%dl
-        movb     %dl,(%edi,%esi,1)
-	subl     $1,%esi
-        subl     $1,%ecx
-        jnz      6b
-7:      cld
-        popl     %edi
-        popl     %esi
-        ret
-
-        / Support for void Copy::conjoint_jshorts_atomic(void* from,
-        /                                                void* to,
-        /                                                size_t count)
-        .align   16
-_Copy_conjoint_jshorts_atomic:
-        pushl    %esi
-        movl     4+12(%esp),%ecx      / count
-        pushl    %edi
-        movl     8+ 4(%esp),%esi      / from
-        movl     8+ 8(%esp),%edi      / to
-        cmpl     %esi,%edi
-        leal     -2(%esi,%ecx,2),%eax / from + count*2 - 2
-        jbe      cs_CopyRight
-        cmpl     %eax,%edi
-        jbe      cs_CopyLeft 
-        / copy from low to high
-cs_CopyRight:
-        / align source address at dword address boundary
-        movl     %esi,%eax            / original from
-        andl     $3,%eax              / either 0 or 2
-        jz       1f                   / no prefix
-        / copy prefix
-        subl     $1,%ecx
-        jl       5f                   / zero count
-        movw     (%esi),%dx
-        movw     %dx,(%edi)
-        addl     %eax,%esi            / %eax == 2
-        addl     %eax,%edi
-1:      movl     %ecx,%eax            / word count less prefix
-        sarl     %ecx                 / dword count
-        jz       4f                   / no dwords to move
-        cmpl     $32,%ecx
-        jbe      2f                   / <= 32 dwords
-        / copy aligned dwords
-        rep;     smovl
-        jmp      4f 
-        / copy aligned dwords
-2:      subl     %esi,%edi
-        .align   16
-3:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        addl     $4,%esi
-        subl     $1,%ecx
-        jnz      3b
-        addl     %esi,%edi
-4:      andl     $1,%eax              / suffix count
-        jz       5f                   / no suffix
-        / copy suffix
-        movw     (%esi),%dx
-        movw     %dx,(%edi)
-5:      popl     %edi
-        popl     %esi
-        ret
-        / copy from high to low
-cs_CopyLeft:
-        std
-        leal     -4(%edi,%ecx,2),%edi / to + count*2 - 4
-        movl     %eax,%esi            / from + count*2 - 2
-        movl     %ecx,%eax
-        subl     $2,%esi              / from + count*2 - 4
-1:      sarl     %ecx                 / dword count
-        jz       4f                   / no dwords to move
-        cmpl     $32,%ecx
-        ja       3f                   / > 32 dwords
-        subl     %esi,%edi
-        .align   16
-2:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        subl     $4,%esi
-        subl     $1,%ecx
-        jnz      2b
-        addl     %esi,%edi
-        jmp      4f
-3:      rep;     smovl
-4:      andl     $1,%eax              / suffix count
-        jz       5f                   / no suffix
-        / copy suffix
-        addl     $2,%esi
-        addl     $2,%edi
-        movw     (%esi),%dx
-        movw     %dx,(%edi)
-5:      cld
-        popl     %edi
-        popl     %esi
-        ret
-
-        / Support for void Copy::arrayof_conjoint_jshorts(void* from,
-        /                                                 void* to,
-        /                                                 size_t count)
-        .align   16
-_Copy_arrayof_conjoint_jshorts:
-        pushl    %esi
-        movl     4+12(%esp),%ecx      / count
-        pushl    %edi
-        movl     8+ 4(%esp),%esi      / from
-        movl     8+ 8(%esp),%edi      / to
-        cmpl     %esi,%edi
-        leal     -2(%esi,%ecx,2),%eax / from + count*2 - 2
-        jbe      acs_CopyRight
-        cmpl     %eax,%edi
-        jbe      acs_CopyLeft 
-acs_CopyRight:
-        movl     %ecx,%eax            / word count
-        sarl     %ecx                 / dword count
-        jz       4f                   / no dwords to move
-        cmpl     $32,%ecx
-        jbe      2f                   / <= 32 dwords
-        / copy aligned dwords
-        rep;     smovl 	 
-        jmp      4f 
-        / copy aligned dwords
-        .=.+5
-2:      subl     %esi,%edi 
-        .align   16	
-3:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        addl     $4,%esi
-        subl     $1,%ecx
-        jnz      3b
-        addl     %esi,%edi
-4:      andl     $1,%eax              / suffix count
-        jz       5f                   / no suffix
-        / copy suffix
-        movw     (%esi),%dx
-        movw     %dx,(%edi)
-5:      popl     %edi
-        popl     %esi
-        ret
-acs_CopyLeft:
-        std
-        leal     -4(%edi,%ecx,2),%edi / to + count*2 - 4
-        movl     %eax,%esi            / from + count*2 - 2
-        movl     %ecx,%eax
-        subl     $2,%esi              / from + count*2 - 4
-        sarl     %ecx                 / dword count
-        jz       4f                   / no dwords to move
-        cmpl     $32,%ecx
-        ja       3f                   / > 32 dwords
-        subl     %esi,%edi
-        .align   16
-2:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        subl     $4,%esi
-        subl     $1,%ecx
-        jnz      2b
-        addl     %esi,%edi
-        jmp      4f
-3:      rep;     smovl
-4:      andl     $1,%eax              / suffix count
-        jz       5f                   / no suffix
-        / copy suffix
-        addl     $2,%esi
-        addl     $2,%edi
-        movw     (%esi),%dx
-        movw     %dx,(%edi)
-5:      cld
-        popl     %edi
-        popl     %esi
-        ret
-
-        / Support for void Copy::conjoint_jints_atomic(void* from,
-        /                                              void* to,
-        /                                              size_t count)
-        / Equivalent to
-        /   arrayof_conjoint_jints
-        .align   16
-_Copy_conjoint_jints_atomic:
-_Copy_arrayof_conjoint_jints:
-        pushl    %esi
-        movl     4+12(%esp),%ecx      / count
-        pushl    %edi
-        movl     8+ 4(%esp),%esi      / from
-        movl     8+ 8(%esp),%edi      / to
-        cmpl     %esi,%edi
-        leal     -4(%esi,%ecx,4),%eax / from + count*4 - 4
-        jbe      ci_CopyRight
-        cmpl     %eax,%edi
-        jbe      ci_CopyLeft 
-ci_CopyRight:
-        cmpl     $32,%ecx
-        jbe      2f                   / <= 32 dwords
-        rep;     smovl 
-        popl     %edi
-        popl     %esi
-        ret
-        .=.+10
-2:      subl     %esi,%edi
-        jmp      4f
-        .align   16
-3:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        addl     $4,%esi
-4:      subl     $1,%ecx
-        jge      3b
-        popl     %edi
-        popl     %esi
-        ret
-ci_CopyLeft:
-        std
-        leal     -4(%edi,%ecx,4),%edi / to + count*4 - 4
-        cmpl     $32,%ecx
-        ja       4f                   / > 32 dwords
-        subl     %eax,%edi            / eax == from + count*4 - 4
-        jmp      3f
-        .align   16
-2:      movl     (%eax),%edx
-        movl     %edx,(%edi,%eax,1)
-        subl     $4,%eax
-3:      subl     $1,%ecx
-        jge      2b
-        cld
-        popl     %edi
-        popl     %esi
-        ret
-4:      movl     %eax,%esi            / from + count*4 - 4
-        rep;     smovl
-        cld
-        popl     %edi
-        popl     %esi
-        ret
-	
-        / Support for void Copy::conjoint_jlongs_atomic(jlong* from,
-        /                                               jlong* to,
-        /                                               size_t count)
-        /
-        / 32-bit
-        /
-        / count treated as signed
-        /
-        / if (from > to) {
-        /   while (--count >= 0) {
-        /     *to++ = *from++;
-        /   }
-        / } else {
-        /   while (--count >= 0) {
-        /     to[count] = from[count];
-        /   }
-        / }
-        .align   16
-_Copy_conjoint_jlongs_atomic:
-        movl     4+8(%esp),%ecx       / count
-        movl     4+0(%esp),%eax       / from
-        movl     4+4(%esp),%edx       / to
-        cmpl     %eax,%edx
-        jae      cla_CopyLeft
-cla_CopyRight:
-        subl     %eax,%edx
-        jmp      2f
-        .align   16
-1:      fildll   (%eax)
-        fistpll  (%edx,%eax,1)
-        addl     $8,%eax
-2:      subl     $1,%ecx
-        jge      1b
-        ret
-        .align   16
-3:      fildll   (%eax,%ecx,8)
-        fistpll  (%edx,%ecx,8)
-cla_CopyLeft:
-        subl     $1,%ecx
-        jge      3b
-        ret
-
-        / Support for void Copy::arrayof_conjoint_jshorts(void* from,
-        /                                                 void* to,
-        /                                                 size_t count)
-       .align   16
-_mmx_Copy_arrayof_conjoint_jshorts:
-        pushl    %esi
-        movl     4+12(%esp),%ecx
-        pushl    %edi
-        movl     8+ 4(%esp),%esi
-        movl     8+ 8(%esp),%edi
-        cmpl     %esi,%edi
-        leal     -2(%esi,%ecx,2),%eax
-        jbe      mmx_acs_CopyRight
-        cmpl     %eax,%edi
-        jbe      mmx_acs_CopyLeft
-mmx_acs_CopyRight:
-        movl     %ecx,%eax
-        sarl     %ecx
-        je       5f
-        cmpl     $33,%ecx
-        jae      3f
-1:      subl     %esi,%edi 
-        .align   16
-2:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        addl     $4,%esi
-        subl     $1,%ecx
-        jnz      2b
-        addl     %esi,%edi
-        jmp      5f 
-3:      smovl / align to 8 bytes, we know we are 4 byte aligned to start
-        subl     $1,%ecx
-4:      .align   16
-        movq     0(%esi),%mm0
-        addl     $64,%edi
-        movq     8(%esi),%mm1
-        subl     $16,%ecx
-        movq     16(%esi),%mm2
-        movq     %mm0,-64(%edi)
-        movq     24(%esi),%mm0
-        movq     %mm1,-56(%edi)
-        movq     32(%esi),%mm1
-        movq     %mm2,-48(%edi)
-        movq     40(%esi),%mm2
-        movq     %mm0,-40(%edi)
-        movq     48(%esi),%mm0
-        movq     %mm1,-32(%edi)
-        movq     56(%esi),%mm1
-        movq     %mm2,-24(%edi)
-        movq     %mm0,-16(%edi)
-        addl     $64,%esi
-        movq     %mm1,-8(%edi)
-        cmpl     $16,%ecx
-        jge      4b
-        emms
-	testl    %ecx,%ecx
-	ja       1b
-5:      andl     $1,%eax
-        je       7f
-6:      movw     (%esi),%dx
-        movw     %dx,(%edi)
-7:      popl     %edi
-        popl     %esi
-        ret
-mmx_acs_CopyLeft:
-        std
-        leal     -4(%edi,%ecx,2),%edi
-        movl     %eax,%esi
-        movl     %ecx,%eax
-        subl     $2,%esi
-        sarl     %ecx
-        je       4f
-        cmpl     $32,%ecx
-        ja       3f
-        subl     %esi,%edi
-        .align   16
-2:      movl     (%esi),%edx
-        movl     %edx,(%edi,%esi,1)
-        subl     $4,%esi
-        subl     $1,%ecx
-        jnz      2b
-        addl     %esi,%edi
-        jmp      4f
-3:      rep;     smovl
-4:      andl     $1,%eax
-        je       6f
-        addl     $2,%esi
-        addl     $2,%edi
-5:      movw     (%esi),%dx
-        movw     %dx,(%edi)
-6:      cld
-        popl     %edi
-        popl     %esi
-        ret
-
-
-        / Support for jlong Atomic::cmpxchg(jlong exchange_value,
-        /                                   volatile jlong* dest,
-        /                                   jlong compare_value)
-        / Used only for Solaris/gcc builds
-        .align 16
-_Atomic_cmpxchg_long_gcc:
-                                   /  8(%esp) : return PC
-        pushl    %ebx              /  4(%esp) : old %ebx
-        pushl    %edi              /  0(%esp) : old %edi
-        movl     12(%esp), %ebx    / 12(%esp) : exchange_value (low)
-        movl     16(%esp), %ecx    / 16(%esp) : exchange_value (high)
-        movl     24(%esp), %eax    / 24(%esp) : compare_value (low)
-        movl     28(%esp), %edx    / 28(%esp) : compare_value (high)
-        movl     20(%esp), %edi    / 20(%esp) : dest
-        lock cmpxchg8b (%edi)
-        popl     %edi
-        popl     %ebx
-        ret
--- a/src/share/vm/adlc/archDesc.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/adlc/archDesc.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -1166,6 +1166,7 @@
          || strcmp(idealName,"CmpP") == 0
          || strcmp(idealName,"CmpN") == 0
          || strcmp(idealName,"CmpL") == 0
+         || strcmp(idealName,"CmpUL") == 0
          || strcmp(idealName,"CmpD") == 0
          || strcmp(idealName,"CmpF") == 0
          || strcmp(idealName,"FastLock") == 0
--- a/src/share/vm/classfile/classLoaderData.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/classLoaderData.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -469,7 +469,8 @@
   InstanceKlass* try_get_next_class() {
     assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
     int max_classes = InstanceKlass::number_of_instance_classes();
-    for (int i = 0; i < max_classes; i++) {
+    assert(max_classes > 0, "should not be called with no instance classes");
+    for (int i = 0; i < max_classes; ) {
 
       if (_current_class_entry != NULL) {
         Klass* k = _current_class_entry;
@@ -477,7 +478,9 @@
 
         if (k->is_instance_klass()) {
           InstanceKlass* ik = InstanceKlass::cast(k);
-          // Only return loaded classes
+          i++;  // count all instance classes found
+          // Not yet loaded classes are counted in max_classes
+          // but only return loaded classes.
           if (ik->is_loaded()) {
             return ik;
           }
@@ -495,9 +498,9 @@
         _current_class_entry = _current_loader_data->klasses();
       }
     }
-    // should never be reached: an InstanceKlass should be returned above
-    ShouldNotReachHere();
-    return NULL;   // Object_klass not even loaded?
+    // Should never be reached unless all instance classes have failed or are not fully loaded.
+    // Caller handles NULL.
+    return NULL;
   }
 
   // If the current class for the static iterator is a class being unloaded or
@@ -1133,12 +1136,22 @@
   }
 }
 
-void ClassLoaderDataGraph::print_dictionary(bool details) {
+void ClassLoaderDataGraph::print_dictionary(outputStream* st) {
   FOR_ALL_DICTIONARY(cld) {
-    tty->print("Dictionary for class loader ");
-    cld->print_value();
-    tty->cr();
-    cld->dictionary()->print(details);
+    st->print("Dictionary for ");
+    cld->print_value_on(st);
+    st->cr();
+    cld->dictionary()->print_on(st);
+    st->cr();
+  }
+}
+
+void ClassLoaderDataGraph::print_dictionary_statistics(outputStream* st) {
+  FOR_ALL_DICTIONARY(cld) {
+    ResourceMark rm;
+    stringStream tempst;
+    tempst.print("System Dictionary for %s", cld->loader_name());
+    cld->dictionary()->print_table_statistics(st, tempst.as_string());
   }
 }
 
@@ -1419,7 +1432,7 @@
 
 void ClassLoaderData::print_value_on(outputStream* out) const {
   if (class_loader() == NULL) {
-    out->print("NULL class_loader");
+    out->print("NULL class loader");
   } else {
     out->print("class loader " INTPTR_FORMAT " ", p2i(this));
     class_loader()->print_value_on(out);
@@ -1428,7 +1441,7 @@
 
 void ClassLoaderData::print_on(outputStream* out) const {
   if (class_loader() == NULL) {
-    out->print("NULL class_loader");
+    out->print("NULL class loader");
   } else {
     out->print("class loader " INTPTR_FORMAT " ", p2i(this));
     class_loader()->print_on(out);
--- a/src/share/vm/classfile/classLoaderData.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/classLoaderData.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -125,7 +125,8 @@
   static InstanceKlass* try_get_next_class();
 
   static void verify_dictionary();
-  static void print_dictionary(bool details);
+  static void print_dictionary(outputStream* st);
+  static void print_dictionary_statistics(outputStream* st);
 
   // CMS support.
   static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); }
--- a/src/share/vm/classfile/compactHashtable.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/compactHashtable.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -29,6 +29,7 @@
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "prims/jvm.h"
+#include "runtime/vmThread.hpp"
 #include "utilities/numberSeq.hpp"
 #include <sys/stat.h>
 
--- a/src/share/vm/classfile/compactHashtable.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/compactHashtable.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,8 @@
 #ifndef SHARE_VM_CLASSFILE_COMPACTHASHTABLE_HPP
 #define SHARE_VM_CLASSFILE_COMPACTHASHTABLE_HPP
 
-#include "classfile/stringTable.hpp"
-#include "classfile/symbolTable.hpp"
+#include "oops/array.hpp"
 #include "oops/symbol.hpp"
-#include "services/diagnosticCommand.hpp"
 #include "utilities/hashtable.hpp"
 
 template <class T, class N> class CompactHashtable;
@@ -357,89 +355,4 @@
   static void put_utf8(outputStream* st, const char* utf8_string, int utf8_length);
 };
 
-///////////////////////////////////////////////////////////////////////
-//
-// jcmd command support for symbol table and string table dumping:
-//   VM.symboltable -verbose: for dumping the symbol table
-//   VM.stringtable -verbose: for dumping the string table
-//
-class VM_DumpHashtable : public VM_Operation {
-private:
-  outputStream* _out;
-  int _which;
-  bool _verbose;
-public:
-  enum {
-    DumpSymbols = 1 << 0,
-    DumpStrings = 1 << 1,
-    DumpSysDict = 1 << 2  // not implemented yet
-  };
-  VM_DumpHashtable(outputStream* out, int which, bool verbose) {
-    _out = out;
-    _which = which;
-    _verbose = verbose;
-  }
-
-  virtual VMOp_Type type() const { return VMOp_DumpHashtable; }
-
-  virtual void doit() {
-    switch (_which) {
-    case DumpSymbols:
-      SymbolTable::dump(_out, _verbose);
-      break;
-    case DumpStrings:
-      StringTable::dump(_out, _verbose);
-      break;
-    default:
-      ShouldNotReachHere();
-    }
-  }
-};
-
-class SymboltableDCmd : public DCmdWithParser {
-protected:
-  DCmdArgument<bool> _verbose;
-public:
-  SymboltableDCmd(outputStream* output, bool heap);
-  static const char* name() {
-    return "VM.symboltable";
-  }
-  static const char* description() {
-    return "Dump symbol table.";
-  }
-  static const char* impact() {
-    return "Medium: Depends on Java content.";
-  }
-  static const JavaPermission permission() {
-    JavaPermission p = {"java.lang.management.ManagementPermission",
-                        "monitor", NULL};
-    return p;
-  }
-  static int num_arguments();
-  virtual void execute(DCmdSource source, TRAPS);
-};
-
-class StringtableDCmd : public DCmdWithParser {
-protected:
-  DCmdArgument<bool> _verbose;
-public:
-  StringtableDCmd(outputStream* output, bool heap);
-  static const char* name() {
-    return "VM.stringtable";
-  }
-  static const char* description() {
-    return "Dump string table.";
-  }
-  static const char* impact() {
-    return "Medium: Depends on Java content.";
-  }
-  static const JavaPermission permission() {
-    JavaPermission p = {"java.lang.management.ManagementPermission",
-                        "monitor", NULL};
-    return p;
-  }
-  static int num_arguments();
-  virtual void execute(DCmdSource source, TRAPS);
-};
-
 #endif // SHARE_VM_CLASSFILE_COMPACTHASHTABLE_HPP
--- a/src/share/vm/classfile/dictionary.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/dictionary.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -435,16 +435,13 @@
 
 // ----------------------------------------------------------------------------
 
-void Dictionary::print(bool details) {
+void Dictionary::print_on(outputStream* st) const {
   ResourceMark rm;
 
   assert(loader_data() != NULL, "loader data should not be null");
-  if (details) {
-    tty->print_cr("Java dictionary (table_size=%d, classes=%d)",
-                   table_size(), number_of_entries());
-    tty->print_cr("^ indicates that initiating loader is different from "
-                  "defining loader");
-  }
+  st->print_cr("Java dictionary (table_size=%d, classes=%d)",
+               table_size(), number_of_entries());
+  st->print_cr("^ indicates that initiating loader is different from defining loader");
 
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry* probe = bucket(index);
@@ -453,17 +450,15 @@
       Klass* e = probe->instance_klass();
       bool is_defining_class =
          (loader_data() == e->class_loader_data());
-      if (details) {
-        tty->print("%4d: ", index);
+      st->print("%4d: %s%s, loader ", index, is_defining_class ? " " : "^", e->external_name());
+      ClassLoaderData* loader_data = e->class_loader_data();
+      if (loader_data == NULL) {
+        // Shared class not restored yet in shared dictionary
+        st->print("<shared, not restored>");
+      } else {
+        loader_data->print_value_on(st);
       }
-      tty->print("%s%s", ((!details) || is_defining_class) ? " " : "^",
-                 e->external_name());
-
-      if (details) {
-        tty->print(", loader ");
-        e->class_loader_data()->print_value();
-      }
-      tty->cr();
+      st->cr();
     }
   }
   tty->cr();
@@ -493,4 +488,3 @@
   tempst.print("System Dictionary for %s", cld->loader_name());
   verify_table<DictionaryEntry>(tempst.as_string());
 }
-
--- a/src/share/vm/classfile/dictionary.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/dictionary.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -103,10 +103,7 @@
   // Sharing support
   void reorder_dictionary();
 
-  void print(bool details = true);
-#ifdef ASSERT
-  void printPerformanceInfoDetails();
-#endif // ASSERT
+  void print_on(outputStream* st) const;
   void verify();
 };
 
@@ -223,7 +220,7 @@
     return (SymbolPropertyEntry**)HashtableEntry<Symbol*, mtSymbol>::next_addr();
   }
 
-  void print_on(outputStream* st) const {
+  void print_entry(outputStream* st) const {
     symbol()->print_value_on(st);
     st->print("/mode=" INTX_FORMAT, symbol_mode());
     st->print(" -> ");
@@ -306,9 +303,6 @@
   // Sharing support
   void reorder_dictionary();
 
-#ifndef PRODUCT
-  void print();
-#endif
   void verify();
 };
 #endif // SHARE_VM_CLASSFILE_DICTIONARY_HPP
--- a/src/share/vm/classfile/loaderConstraints.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/loaderConstraints.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -466,27 +466,24 @@
   }
 }
 
-#ifndef PRODUCT
-
 // Called with the system dictionary lock held
-void LoaderConstraintTable::print() {
+void LoaderConstraintTable::print_on(outputStream* st) const {
   ResourceMark rm;
   assert_locked_or_safepoint(SystemDictionary_lock);
-  tty->print_cr("Java loader constraints (entries=%d, constraints=%d)",
-                table_size(), number_of_entries());
+  st->print_cr("Java loader constraints (table_size=%d, constraints=%d)",
+               table_size(), number_of_entries());
   for (int cindex = 0; cindex < table_size(); cindex++) {
     for (LoaderConstraintEntry* probe = bucket(cindex);
                                 probe != NULL;
                                 probe = probe->next()) {
-      tty->print("%4d: ", cindex);
-      probe->name()->print();
-      tty->print(" , loaders:");
+      st->print("%4d: ", cindex);
+      probe->name()->print_on(st);
+      st->print(" , loaders:");
       for (int n = 0; n < probe->num_loaders(); n++) {
-        probe->loader_data(n)->print_value();
-        tty->print(", ");
+        probe->loader_data(n)->print_value_on(st);
+        st->print(", ");
       }
-      tty->cr();
+      st->cr();
     }
   }
 }
-#endif
--- a/src/share/vm/classfile/loaderConstraints.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/loaderConstraints.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -47,7 +47,7 @@
                                    int max_loaders);
   void free_entry(LoaderConstraintEntry *entry);
 
-  LoaderConstraintEntry* bucket(int i) {
+  LoaderConstraintEntry* bucket(int i) const {
     return (LoaderConstraintEntry*)Hashtable<InstanceKlass*, mtClass>::bucket(i);
   }
 
@@ -79,9 +79,7 @@
   void purge_loader_constraints();
 
   void verify(PlaceholderTable* placeholders);
-#ifndef PRODUCT
-  void print();
-#endif
+  void print_on(outputStream* st) const;
 };
 
 class LoaderConstraintEntry : public HashtableEntry<InstanceKlass*, mtClass> {
--- a/src/share/vm/classfile/placeholders.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/placeholders.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -175,39 +175,6 @@
     : Hashtable<Symbol*, mtClass>(table_size, sizeof(PlaceholderEntry)) {
 }
 
-#ifndef PRODUCT
-// Note, doesn't append a cr
-void PlaceholderEntry::print() const {
-  klassname()->print_value();
-  if (loader_data() != NULL) {
-    tty->print(", loader ");
-    loader_data()->print_value();
-  }
-  if (supername() != NULL) {
-    tty->print(", supername ");
-    supername()->print_value();
-  }
-  if (definer() != NULL) {
-    tty->print(", definer ");
-    definer()->print_value();
-  }
-  if (instance_klass() != NULL) {
-    tty->print(", InstanceKlass ");
-    instance_klass()->print_value();
-  }
-  tty->print("\n");
-  tty->print("loadInstanceThreadQ threads:");
-  loadInstanceThreadQ()->printActionQ();
-  tty->print("\n");
-  tty->print("superThreadQ threads:");
-  superThreadQ()->printActionQ();
-  tty->print("\n");
-  tty->print("defineThreadQ threads:");
-  defineThreadQ()->printActionQ();
-  tty->print("\n");
-}
-#endif
-
 void PlaceholderEntry::verify() const {
   guarantee(loader_data() != NULL, "Must have been setup.");
   guarantee(loader_data()->class_loader() == NULL || loader_data()->class_loader()->is_instance(),
@@ -222,20 +189,48 @@
 }
 
 
-#ifndef PRODUCT
-void PlaceholderTable::print() {
-  tty->print_cr("Placeholder table table_size=%d, entries=%d",
+// Note, doesn't append a cr
+// Can't call this print_on because HashtableEntry doesn't initialize its vptr
+// and print_on is a virtual function so the vptr call crashes.
+void PlaceholderEntry::print_entry(outputStream* st) const {
+  klassname()->print_value_on(st);
+  if (loader_data() != NULL) {
+    st->print(", loader ");
+    loader_data()->print_value_on(st);
+  }
+  if (supername() != NULL) {
+    st->print(", supername ");
+    supername()->print_value_on(st);
+  }
+  if (definer() != NULL) {
+    st->print(", definer ");
+    definer()->print_value_on(st);
+  }
+  if (instance_klass() != NULL) {
+    st->print(", InstanceKlass ");
+    instance_klass()->print_value_on(st);
+  }
+  st->cr();
+  st->print("loadInstanceThreadQ threads:");
+  loadInstanceThreadQ()->print_action_queue(st);
+  st->cr();
+  st->print("superThreadQ threads:");
+  superThreadQ()->print_action_queue(st);
+  st->cr();
+  st->print("defineThreadQ threads:");
+  defineThreadQ()->print_action_queue(st);
+  st->cr();
+}
+
+void PlaceholderTable::print_on(outputStream* st) const {
+  st->print_cr("Placeholder table (table_size=%d, placeholders=%d)",
                 table_size(), number_of_entries());
   for (int pindex = 0; pindex < table_size(); pindex++) {
     for (PlaceholderEntry* probe = bucket(pindex);
                            probe != NULL;
                            probe = probe->next()) {
-      tty->print("%4d: ", pindex);
-      tty->print(" place holder ");
-
-      probe->print();
-      tty->cr();
+      st->print("%4d: placeholder ", pindex);
+      probe->print_entry(st);
     }
   }
 }
-#endif
--- a/src/share/vm/classfile/placeholders.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/placeholders.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -42,7 +42,7 @@
   PlaceholderEntry* new_entry(int hash, Symbol* name, ClassLoaderData* loader_data, bool havesupername, Symbol* supername);
   void free_entry(PlaceholderEntry* entry);
 
-  PlaceholderEntry* bucket(int i) {
+  PlaceholderEntry* bucket(int i) const {
     return (PlaceholderEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
   }
 
@@ -97,9 +97,7 @@
                        Symbol* name, ClassLoaderData* loader_data,
                        classloadAction action, Thread* thread);
 
-#ifndef PRODUCT
-  void print();
-#endif
+  void print_on(outputStream* st) const;
   void verify();
 };
 
@@ -129,16 +127,14 @@
    void set_next(SeenThread *seen) { _stnext = seen; }
    void set_prev(SeenThread *seen) { _stprev = seen; }
 
-#ifndef PRODUCT
-  void printActionQ() {
+  void print_action_queue(outputStream* st) {
     SeenThread* seen = this;
     while (seen != NULL) {
-      seen->thread()->print_value();
-      tty->print(", ");
+      seen->thread()->print_value_on(st);
+      st->print(", ");
       seen = seen->next();
     }
   }
-#endif // PRODUCT
 };
 
 // Placeholder objects represent classes currently being loaded.
@@ -321,7 +317,7 @@
   }
 
   // Print method doesn't append a cr
-  void print() const  PRODUCT_RETURN;
+  void print_entry(outputStream* st) const;
   void verify() const;
 };
 
--- a/src/share/vm/classfile/protectionDomainCache.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/protectionDomainCache.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -80,25 +80,18 @@
   }
 }
 
-#ifndef PRODUCT
-void ProtectionDomainCacheTable::print() {
-  tty->print_cr("Protection domain cache table (table_size=%d, classes=%d)",
-                table_size(), number_of_entries());
+void ProtectionDomainCacheTable::print_on(outputStream* st) const {
+  st->print_cr("Protection domain cache table (table_size=%d, classes=%d)",
+               table_size(), number_of_entries());
   for (int index = 0; index < table_size(); index++) {
     for (ProtectionDomainCacheEntry* probe = bucket(index);
                                      probe != NULL;
                                      probe = probe->next()) {
-      tty->print("%4d: ", index);
-      probe->print();
+      st->print_cr("%4d: protection_domain: " PTR_FORMAT, index, p2i(probe->literal()));
     }
   }
 }
 
-void ProtectionDomainCacheEntry::print() {
-  tty->print_cr("protection_domain: " PTR_FORMAT, p2i(literal()));
-}
-#endif
-
 void ProtectionDomainCacheTable::verify() {
   verify_table<ProtectionDomainCacheEntry>("Protection Domain Table");
 }
--- a/src/share/vm/classfile/protectionDomainCache.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/protectionDomainCache.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -51,7 +51,6 @@
     f->do_oop(literal_addr());
   }
 
-  void print() PRODUCT_RETURN;
   void verify();
 };
 
@@ -67,7 +66,7 @@
 class ProtectionDomainCacheTable : public Hashtable<oop, mtClass> {
   friend class VMStructs;
 private:
-  ProtectionDomainCacheEntry* bucket(int i) {
+  ProtectionDomainCacheEntry* bucket(int i) const {
     return (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::bucket(i);
   }
 
@@ -96,7 +95,7 @@
   // GC support
   void oops_do(OopClosure* f);
 
-  void print() PRODUCT_RETURN;
+  void print_on(outputStream* st) const;
   void verify();
 };
 
--- a/src/share/vm/classfile/stringTable.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/stringTable.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -37,6 +37,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "services/diagnosticCommand.hpp"
 #include "utilities/hashtable.inline.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
@@ -439,7 +440,7 @@
 
 void StringTable::dump(outputStream* st, bool verbose) {
   if (!verbose) {
-    the_table()->dump_table(st, "StringTable");
+    the_table()->print_table_statistics(st, "StringTable");
   } else {
     Thread* THREAD = Thread::current();
     st->print_cr("VERSION: 1.1");
--- a/src/share/vm/classfile/symbolTable.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/symbolTable.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -36,6 +36,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "services/diagnosticCommand.hpp"
 #include "utilities/hashtable.inline.hpp"
 
 // --------------------------------------------------------------------------
@@ -550,7 +551,7 @@
 
 void SymbolTable::dump(outputStream* st, bool verbose) {
   if (!verbose) {
-    the_table()->dump_table(st, "SymbolTable");
+    the_table()->print_table_statistics(st, "SymbolTable");
   } else {
     st->print_cr("VERSION: 1.0");
     for (int i = 0; i < the_table()->table_size(); ++i) {
--- a/src/share/vm/classfile/systemDictionary.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/systemDictionary.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -74,6 +74,7 @@
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/signature.hpp"
 #include "services/classLoadingService.hpp"
+#include "services/diagnosticCommand.hpp"
 #include "services/threadService.hpp"
 #include "trace/traceMacros.hpp"
 #include "utilities/macros.hpp"
@@ -2808,33 +2809,32 @@
 }
 
 // ----------------------------------------------------------------------------
-void SystemDictionary::print_shared(bool details) {
-  shared_dictionary()->print(details);
+void SystemDictionary::print_shared(outputStream *st) {
+  shared_dictionary()->print_on(st);
 }
 
-void SystemDictionary::print(bool details) {
+void SystemDictionary::print_on(outputStream *st) {
   if (shared_dictionary() != NULL) {
     tty->print_cr("Shared Dictionary");
-    shared_dictionary()->print(details);
+    shared_dictionary()->print_on(st);
   }
 
   GCMutexLocker mu(SystemDictionary_lock);
 
-  ClassLoaderDataGraph::print_dictionary(details);
+  ClassLoaderDataGraph::print_dictionary(st);
 
   // Placeholders
-  placeholders()->print();
-  tty->cr();
+  placeholders()->print_on(st);
+  st->cr();
 
   // loader constraints - print under SD_lock
-  constraints()->print();
-  tty->cr();
-
-  _pd_cache_table->print();
-  tty->cr();
+  constraints()->print_on(st);
+  st->cr();
+
+  _pd_cache_table->print_on(st);
+  st->cr();
 }
 
-
 void SystemDictionary::verify() {
   guarantee(constraints() != NULL,
             "Verify of loader constraints failed");
@@ -2855,6 +2855,44 @@
   _pd_cache_table->verify();
 }
 
+void SystemDictionary::dump(outputStream *st, bool verbose) {
+  assert_locked_or_safepoint(SystemDictionary_lock);
+  if (verbose) {
+    print_on(st);
+  } else {
+    ClassLoaderDataGraph::print_dictionary_statistics(st);
+    placeholders()->print_table_statistics(st, "Placeholder Table");
+    constraints()->print_table_statistics(st, "LoaderConstraints Table");
+    _pd_cache_table->print_table_statistics(st, "ProtectionDomainCache Table");
+  }
+}
+
+// Utility for dumping dictionaries.
+SystemDictionaryDCmd::SystemDictionaryDCmd(outputStream* output, bool heap) :
+                                 DCmdWithParser(output, heap),
+  _verbose("-verbose", "Dump the content of each dictionary entry for all class loaders",
+           "BOOLEAN", false, "false") {
+  _dcmdparser.add_dcmd_option(&_verbose);
+}
+
+void SystemDictionaryDCmd::execute(DCmdSource source, TRAPS) {
+  VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpSysDict,
+                         _verbose.value());
+  VMThread::execute(&dumper);
+}
+
+int SystemDictionaryDCmd::num_arguments() {
+  ResourceMark rm;
+  SystemDictionaryDCmd* dcmd = new SystemDictionaryDCmd(NULL, false);
+  if (dcmd != NULL) {
+    DCmdMark mark(dcmd);
+    return dcmd->_dcmdparser.num_arguments();
+  } else {
+    return 0;
+  }
+}
+
+
 // caller needs ResourceMark
 const char* SystemDictionary::loader_name(const oop loader) {
   return ((loader) == NULL ? "<bootloader>" :
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -388,8 +388,10 @@
   static void set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
                                     int number_of_entries);
   // Printing
-  static void print(bool details = true);
-  static void print_shared(bool details = true);
+  static void print() { return print_on(tty); }
+  static void print_on(outputStream* st);
+  static void print_shared(outputStream* st);
+  static void dump(outputStream* st, bool verbose);
 
   // Monotonically increasing counter which grows as classes are
   // loaded or modifications such as hot-swapping or setting/removing
--- a/src/share/vm/gc/shared/genCollectedHeap.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/gc/shared/genCollectedHeap.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "aot/aotLoader.hpp"
 #include "classfile/symbolTable.hpp"
+#include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/codeCache.hpp"
--- a/src/share/vm/interpreter/rewriter.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/interpreter/rewriter.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -27,6 +27,7 @@
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/rewriter.hpp"
+#include "memory/metadataFactory.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/generateOopMap.hpp"
@@ -101,7 +102,13 @@
   // the above lines.
   _pool->initialize_resolved_references(loader_data, _resolved_references_map,
                                         _resolved_reference_limit,
-                                        CHECK);
+                                        THREAD);
+
+  // Clean up constant pool cache if initialize_resolved_references() failed.
+  if (HAS_PENDING_EXCEPTION) {
+    MetadataFactory::free_metadata(loader_data, cache);
+    _pool->set_cache(NULL);  // so the verifier isn't confused
+  }
 }
 
 
--- a/src/share/vm/logging/logTag.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/logging/logTag.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -142,6 +142,7 @@
   LOG_TAG(verification) \
   LOG_TAG(verify) \
   LOG_TAG(vmoperation) \
+  LOG_TAG(vmthread) \
   LOG_TAG(vtables) \
   LOG_TAG(workgang) \
   LOG_TAG_LIST_EXT
--- a/src/share/vm/memory/filemap.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/memory/filemap.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -26,6 +26,7 @@
 #include "classfile/classLoader.hpp"
 #include "classfile/compactHashtable.inline.hpp"
 #include "classfile/sharedClassUtil.hpp"
+#include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "classfile/altHashing.hpp"
--- a/src/share/vm/memory/filemap.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/memory/filemap.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,10 @@
 #ifndef SHARE_VM_MEMORY_FILEMAP_HPP
 #define SHARE_VM_MEMORY_FILEMAP_HPP
 
+#include "classfile/classLoader.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/metaspace.hpp"
+#include "memory/universe.hpp"
 #include "utilities/align.hpp"
 
 // Layout of the file:
--- a/src/share/vm/memory/metaspaceShared.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/memory/metaspaceShared.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -30,6 +30,7 @@
 #include "classfile/placeholders.hpp"
 #include "classfile/sharedClassUtil.hpp"
 #include "classfile/symbolTable.hpp"
+#include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "code/codeCache.hpp"
@@ -1328,7 +1329,7 @@
   if (PrintSharedArchiveAndExit) {
     if (PrintSharedDictionary) {
       tty->print_cr("\nShared classes:\n");
-      SystemDictionary::print_shared(false);
+      SystemDictionary::print_shared(tty);
     }
     if (_archive_loading_failed) {
       tty->print_cr("archive is invalid");
--- a/src/share/vm/opto/arraycopynode.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/arraycopynode.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -748,41 +748,3 @@
   return false;
 }
 
-// We try to replace a load from the destination of an arraycopy with
-// a load from the source so the arraycopy has a chance to be
-// eliminated. It's only valid if the arraycopy doesn't change the
-// element that would be loaded from the source array.
-bool ArrayCopyNode::can_replace_dest_load_with_src_load(intptr_t offset_lo, intptr_t offset_hi, PhaseTransform* phase) const {
-  assert(_kind == ArrayCopy || _kind == CopyOf || _kind == CopyOfRange, "only for real array copies");
-
-  Node* src = in(Src);
-  Node* dest = in(Dest);
-
-  // Check whether, assuming source and destination are the same
-  // array, the arraycopy modifies the element from the source we
-  // would load.
-  if ((src != dest && in(SrcPos) == in(DestPos)) || !modifies(offset_lo, offset_hi, phase, false)) {
-    // if not the transformation is legal
-    return true;
-  }
-
-  AllocateNode* src_alloc = AllocateNode::Ideal_allocation(src, phase);
-  AllocateNode* dest_alloc = AllocateNode::Ideal_allocation(dest, phase);
-
-  // Check whether source and destination can be proved to be
-  // different arrays
-  const TypeOopPtr* t_src = phase->type(src)->isa_oopptr();
-  const TypeOopPtr* t_dest = phase->type(dest)->isa_oopptr();
-
-  if (t_src != NULL && t_dest != NULL &&
-      (t_src->is_known_instance() || t_dest->is_known_instance()) &&
-      t_src->instance_id() != t_dest->instance_id()) {
-    return true;
-  }
-
-  if (MemNode::detect_ptr_independence(src->uncast(), src_alloc, dest->uncast(), dest_alloc, phase)) {
-    return true;
-  }
-
-  return false;
-}
--- a/src/share/vm/opto/arraycopynode.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/arraycopynode.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -168,7 +168,6 @@
 
   static bool may_modify(const TypeOopPtr *t_oop, MemBarNode* mb, PhaseTransform *phase, ArrayCopyNode*& ac);
   bool modifies(intptr_t offset_lo, intptr_t offset_hi, PhaseTransform* phase, bool must_modify) const;
-  bool can_replace_dest_load_with_src_load(intptr_t offset_lo, intptr_t offset_hi, PhaseTransform* phase) const;
 
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
--- a/src/share/vm/opto/c2_globals.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/c2_globals.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -181,7 +181,7 @@
            "Map number of unrolls for main loop via "                       \
            "Superword Level Parallelism analysis")                          \
                                                                             \
-  diagnostic_pd(bool, PostLoopMultiversioning,                              \
+  experimental(bool, PostLoopMultiversioning, false,                        \
            "Multi versioned post loops to eliminate range checks")          \
                                                                             \
   notproduct(bool, TraceSuperWordLoopUnrollAnalysis, false,                 \
--- a/src/share/vm/opto/classes.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/classes.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -81,6 +81,7 @@
 macro(CmpLTMask)
 macro(CmpP)
 macro(CmpU)
+macro(CmpUL)
 macro(CompareAndSwapB)
 macro(CompareAndSwapS)
 macro(CompareAndSwapI)
--- a/src/share/vm/opto/library_call.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/library_call.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -5250,6 +5250,10 @@
                     Deoptimization::Action_make_not_entrant);
       assert(stopped(), "Should be stopped");
     }
+
+    const TypeKlassPtr* dest_klass_t = _gvn.type(dest_klass)->is_klassptr();
+    const Type *toop = TypeOopPtr::make_from_klass(dest_klass_t->klass());
+    src = _gvn.transform(new CheckCastPPNode(control(), src, toop));
   }
 
   arraycopy_move_allocation_here(alloc, dest, saved_jvms, saved_reexecute_sp, new_idx);
--- a/src/share/vm/opto/loopPredicate.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/loopPredicate.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -29,6 +29,7 @@
 #include "opto/connode.hpp"
 #include "opto/convertnode.hpp"
 #include "opto/loopnode.hpp"
+#include "opto/matcher.hpp"
 #include "opto/mulnode.hpp"
 #include "opto/opaquenode.hpp"
 #include "opto/rootnode.hpp"
@@ -629,49 +630,150 @@
 //   max(scale*i + offset) = scale*init + offset
 BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
                                        int scale, Node* offset,
-                                       Node* init, Node* limit, Node* stride,
-                                       Node* range, bool upper) {
+                                       Node* init, Node* limit, jint stride,
+                                       Node* range, bool upper, bool &overflow) {
+  jint con_limit  = limit->is_Con()  ? limit->get_int()  : 0;
+  jint con_init   = init->is_Con()   ? init->get_int()   : 0;
+  jint con_offset = offset->is_Con() ? offset->get_int() : 0;
+
   stringStream* predString = NULL;
   if (TraceLoopPredicate) {
     predString = new stringStream();
     predString->print("rc_predicate ");
   }
 
-  Node* max_idx_expr  = init;
-  int stride_con = stride->get_int();
-  if ((stride_con > 0) == (scale > 0) == upper) {
-    // Limit is not exact.
-    // Calculate exact limit here.
-    // Note, counted loop's test is '<' or '>'.
-    limit = exact_limit(loop);
-    max_idx_expr = new SubINode(limit, stride);
+  overflow = false;
+  Node* max_idx_expr = NULL;
+  const TypeInt* idx_type = TypeInt::INT;
+  if ((stride > 0) == (scale > 0) == upper) {
+    if (TraceLoopPredicate) {
+      if (limit->is_Con()) {
+        predString->print("(%d ", con_limit);
+      } else {
+        predString->print("(limit ");
+      }
+      predString->print("- %d) ", stride);
+    }
+    // Check if (limit - stride) may overflow
+    const TypeInt* limit_type = _igvn.type(limit)->isa_int();
+    jint limit_lo = limit_type->_lo;
+    jint limit_hi = limit_type->_hi;
+    if ((stride > 0 && (java_subtract(limit_lo, stride) < limit_lo)) ||
+        (stride < 0 && (java_subtract(limit_hi, stride) > limit_hi))) {
+      // No overflow possible
+      ConINode* con_stride = _igvn.intcon(stride);
+      set_ctrl(con_stride, C->root());
+      max_idx_expr = new SubINode(limit, con_stride);
+      idx_type = TypeInt::make(limit_lo - stride, limit_hi - stride, limit_type->_widen);
+    } else {
+      // May overflow
+      overflow = true;
+      limit = new ConvI2LNode(limit);
+      register_new_node(limit, ctrl);
+      ConLNode* con_stride = _igvn.longcon(stride);
+      set_ctrl(con_stride, C->root());
+      max_idx_expr = new SubLNode(limit, con_stride);
+    }
     register_new_node(max_idx_expr, ctrl);
-    if (TraceLoopPredicate) predString->print("(limit - stride) ");
   } else {
-    if (TraceLoopPredicate) predString->print("init ");
+    if (TraceLoopPredicate) {
+      if (init->is_Con()) {
+        predString->print("%d ", con_init);
+      } else {
+        predString->print("init ");
+      }
+    }
+    idx_type = _igvn.type(init)->isa_int();
+    max_idx_expr = init;
   }
 
   if (scale != 1) {
     ConNode* con_scale = _igvn.intcon(scale);
     set_ctrl(con_scale, C->root());
-    max_idx_expr = new MulINode(max_idx_expr, con_scale);
+    if (TraceLoopPredicate) {
+      predString->print("* %d ", scale);
+    }
+    // Check if (scale * max_idx_expr) may overflow
+    const TypeInt* scale_type = TypeInt::make(scale);
+    MulINode* mul = new MulINode(max_idx_expr, con_scale);
+    idx_type = (TypeInt*)mul->mul_ring(idx_type, scale_type);
+    if (overflow || TypeInt::INT->higher_equal(idx_type)) {
+      // May overflow
+      mul->destruct();
+      if (!overflow) {
+        max_idx_expr = new ConvI2LNode(max_idx_expr);
+        register_new_node(max_idx_expr, ctrl);
+      }
+      overflow = true;
+      con_scale = _igvn.longcon(scale);
+      set_ctrl(con_scale, C->root());
+      max_idx_expr = new MulLNode(max_idx_expr, con_scale);
+    } else {
+      // No overflow possible
+      max_idx_expr = mul;
+    }
     register_new_node(max_idx_expr, ctrl);
-    if (TraceLoopPredicate) predString->print("* %d ", scale);
   }
 
-  if (offset && (!offset->is_Con() || offset->get_int() != 0)){
-    max_idx_expr = new AddINode(max_idx_expr, offset);
-    register_new_node(max_idx_expr, ctrl);
+  if (offset && (!offset->is_Con() || con_offset != 0)){
     if (TraceLoopPredicate) {
       if (offset->is_Con()) {
-        predString->print("+ %d ", offset->get_int());
+        predString->print("+ %d ", con_offset);
       } else {
-        predString->print("+ offset ");
+        predString->print("+ offset");
       }
     }
+    // Check if (max_idx_expr + offset) may overflow
+    const TypeInt* offset_type = _igvn.type(offset)->isa_int();
+    jint lo = java_add(idx_type->_lo, offset_type->_lo);
+    jint hi = java_add(idx_type->_hi, offset_type->_hi);
+    if (overflow || (lo > hi) ||
+        ((idx_type->_lo & offset_type->_lo) < 0 && lo >= 0) ||
+        ((~(idx_type->_hi | offset_type->_hi)) < 0 && hi < 0)) {
+      // May overflow
+      if (!overflow) {
+        max_idx_expr = new ConvI2LNode(max_idx_expr);
+        register_new_node(max_idx_expr, ctrl);
+      }
+      overflow = true;
+      offset = new ConvI2LNode(offset);
+      register_new_node(offset, ctrl);
+      max_idx_expr = new AddLNode(max_idx_expr, offset);
+    } else {
+      // No overflow possible
+      max_idx_expr = new AddINode(max_idx_expr, offset);
+    }
+    register_new_node(max_idx_expr, ctrl);
   }
 
-  CmpUNode* cmp = new CmpUNode(max_idx_expr, range);
+  CmpNode* cmp = NULL;
+  if (overflow) {
+    // Integer expressions may overflow, do long comparison
+    range = new ConvI2LNode(range);
+    register_new_node(range, ctrl);
+    if (!Matcher::has_match_rule(Op_CmpUL)) {
+      // We don't support unsigned long comparisons. Set 'max_idx_expr'
+      // to max_julong if < 0 to make the signed comparison fail.
+      ConINode* sign_pos = _igvn.intcon(BitsPerLong - 1);
+      set_ctrl(sign_pos, C->root());
+      Node* sign_bit_mask = new RShiftLNode(max_idx_expr, sign_pos);
+      register_new_node(sign_bit_mask, ctrl);
+      // OR with sign bit to set all bits to 1 if negative (otherwise no change)
+      max_idx_expr = new OrLNode(max_idx_expr, sign_bit_mask);
+      register_new_node(max_idx_expr, ctrl);
+      // AND with 0x7ff... to unset the sign bit
+      ConLNode* remove_sign_mask = _igvn.longcon(max_jlong);
+      set_ctrl(remove_sign_mask, C->root());
+      max_idx_expr = new AndLNode(max_idx_expr, remove_sign_mask);
+      register_new_node(max_idx_expr, ctrl);
+
+      cmp = new CmpLNode(max_idx_expr, range);
+    } else {
+      cmp = new CmpULNode(max_idx_expr, range);
+    }
+  } else {
+    cmp = new CmpUNode(max_idx_expr, range);
+  }
   register_new_node(cmp, ctrl);
   BoolNode* bol = new BoolNode(cmp, BoolTest::lt);
   register_new_node(bol, ctrl);
@@ -818,28 +920,30 @@
       assert(ok, "must be index expression");
 
       Node* init    = cl->init_trip();
-      Node* limit   = cl->limit();
-      Node* stride  = cl->stride();
+      // Limit is not exact.
+      // Calculate exact limit here.
+      // Note, counted loop's test is '<' or '>'.
+      Node* limit   = exact_limit(loop);
+      int  stride   = cl->stride()->get_int();
 
       // Build if's for the upper and lower bound tests.  The
       // lower_bound test will dominate the upper bound test and all
       // cloned or created nodes will use the lower bound test as
       // their declared control.
-      ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, iff->Opcode());
-      ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, iff->Opcode());
-      assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
-      Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0);
 
       // Perform cloning to keep Invariance state correct since the
       // late schedule will place invariant things in the loop.
+      Node *ctrl = predicate_proj->in(0)->as_If()->in(0);
       rng = invar.clone(rng, ctrl);
       if (offset && offset != zero) {
         assert(invar.is_invariant(offset), "offset must be loop invariant");
         offset = invar.clone(offset, ctrl);
       }
+      // If predicate expressions may overflow in the integer range, longs are used.
+      bool overflow = false;
 
       // Test the lower bound
-      BoolNode*  lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false);
+      BoolNode* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow);
       // Negate test if necessary
       bool negated = false;
       if (proj->_con != predicate_proj->_con) {
@@ -847,19 +951,22 @@
         register_new_node(lower_bound_bol, ctrl);
         negated = true;
       }
+      ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, overflow ? Op_If : iff->Opcode());
       IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
       _igvn.hash_delete(lower_bound_iff);
       lower_bound_iff->set_req(1, lower_bound_bol);
       if (TraceLoopPredicate) tty->print_cr("lower bound check if: %s %d ", negated ? " negated" : "", lower_bound_iff->_idx);
 
       // Test the upper bound
-      BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true);
+      BoolNode* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow);
       negated = false;
       if (proj->_con != predicate_proj->_con) {
         upper_bound_bol = new BoolNode(upper_bound_bol->in(1), upper_bound_bol->_test.negate());
         register_new_node(upper_bound_bol, ctrl);
         negated = true;
       }
+      ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate, overflow ? Op_If : iff->Opcode());
+      assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
       IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
       _igvn.hash_delete(upper_bound_iff);
       upper_bound_iff->set_req(1, upper_bound_bol);
--- a/src/share/vm/opto/loopnode.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/loopnode.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -983,8 +983,8 @@
   // Construct a range check for a predicate if
   BoolNode* rc_predicate(IdealLoopTree *loop, Node* ctrl,
                          int scale, Node* offset,
-                         Node* init, Node* limit, Node* stride,
-                         Node* range, bool upper);
+                         Node* init, Node* limit, jint stride,
+                         Node* range, bool upper, bool &overflow);
 
   // Implementation of the loop predication to promote checks outside the loop
   bool loop_predication_impl(IdealLoopTree *loop);
--- a/src/share/vm/opto/memnode.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/memnode.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -890,7 +890,7 @@
 // Is the value loaded previously stored by an arraycopy? If so return
 // a load node that reads from the source array so we may be able to
 // optimize out the ArrayCopy node later.
-Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseTransform* phase) const {
+Node* LoadNode::can_see_arraycopy_value(Node* st, PhaseGVN* phase) const {
   Node* ld_adr = in(MemNode::Address);
   intptr_t ld_off = 0;
   AllocateNode* ld_alloc = AllocateNode::Ideal_allocation(ld_adr, phase, ld_off);
@@ -898,23 +898,27 @@
   if (ac != NULL) {
     assert(ac->is_ArrayCopy(), "what kind of node can this be?");
 
-    Node* ld = clone();
+    Node* mem = ac->in(TypeFunc::Memory);
+    Node* ctl = ac->in(0);
+    Node* src = ac->in(ArrayCopyNode::Src);
+
+    if (!ac->as_ArrayCopy()->is_clonebasic() && !phase->type(src)->isa_aryptr()) {
+      return NULL;
+    }
+
+    LoadNode* ld = clone()->as_Load();
+    Node* addp = in(MemNode::Address)->clone();
     if (ac->as_ArrayCopy()->is_clonebasic()) {
       assert(ld_alloc != NULL, "need an alloc");
-      Node* addp = in(MemNode::Address)->clone();
       assert(addp->is_AddP(), "address must be addp");
       assert(addp->in(AddPNode::Base) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Base), "strange pattern");
       assert(addp->in(AddPNode::Address) == ac->in(ArrayCopyNode::Dest)->in(AddPNode::Address), "strange pattern");
-      addp->set_req(AddPNode::Base, ac->in(ArrayCopyNode::Src)->in(AddPNode::Base));
-      addp->set_req(AddPNode::Address, ac->in(ArrayCopyNode::Src)->in(AddPNode::Address));
-      ld->set_req(MemNode::Address, phase->transform(addp));
-      if (in(0) != NULL) {
-        assert(ld_alloc->in(0) != NULL, "alloc must have control");
-        ld->set_req(0, ld_alloc->in(0));
-      }
+      addp->set_req(AddPNode::Base, src->in(AddPNode::Base));
+      addp->set_req(AddPNode::Address, src->in(AddPNode::Address));
     } else {
-      Node* src = ac->in(ArrayCopyNode::Src);
-      Node* addp = in(MemNode::Address)->clone();
+      assert(ac->as_ArrayCopy()->is_arraycopy_validated() ||
+             ac->as_ArrayCopy()->is_copyof_validated() ||
+             ac->as_ArrayCopy()->is_copyofrange_validated(), "only supported cases");
       assert(addp->in(AddPNode::Base) == addp->in(AddPNode::Address), "should be");
       addp->set_req(AddPNode::Base, src);
       addp->set_req(AddPNode::Address, src);
@@ -932,21 +936,17 @@
 
       Node* offset = phase->transform(new AddXNode(addp->in(AddPNode::Offset), diff));
       addp->set_req(AddPNode::Offset, offset);
-      ld->set_req(MemNode::Address, phase->transform(addp));
-
-      const TypeX *ld_offs_t = phase->type(offset)->isa_intptr_t();
-
-      if (!ac->as_ArrayCopy()->can_replace_dest_load_with_src_load(ld_offs_t->_lo, ld_offs_t->_hi, phase)) {
-        return NULL;
-      }
-
-      if (in(0) != NULL) {
-        assert(ac->in(0) != NULL, "alloc must have control");
-        ld->set_req(0, ac->in(0));
-      }
     }
+    addp = phase->transform(addp);
+#ifdef ASSERT
+    const TypePtr* adr_type = phase->type(addp)->is_ptr();
+    ld->_adr_type = adr_type;
+#endif
+    ld->set_req(MemNode::Address, addp);
+    ld->set_req(0, ctl);
+    ld->set_req(MemNode::Memory, mem);
     // load depends on the tests that validate the arraycopy
-    ld->as_Load()->_control_dependency = Pinned;
+    ld->_control_dependency = Pinned;
     return ld;
   }
   return NULL;
--- a/src/share/vm/opto/memnode.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/memnode.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -270,7 +270,7 @@
   const Type* load_array_final_field(const TypeKlassPtr *tkls,
                                      ciKlass* klass) const;
 
-  Node* can_see_arraycopy_value(Node* st, PhaseTransform* phase) const;
+  Node* can_see_arraycopy_value(Node* st, PhaseGVN* phase) const;
 
   // depends_only_on_test is almost always true, and needs to be almost always
   // true to enable key hoisting & commoning optimizations.  However, for the
--- a/src/share/vm/opto/output.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/output.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -1982,6 +1982,7 @@
     if( last->is_MachIf() && last->in(1) == n &&
         ( op == Op_CmpI ||
           op == Op_CmpU ||
+          op == Op_CmpUL ||
           op == Op_CmpP ||
           op == Op_CmpF ||
           op == Op_CmpD ||
--- a/src/share/vm/opto/subnode.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/subnode.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -738,6 +738,60 @@
   return TypeInt::CC;           // else use worst case results
 }
 
+
+// Simplify a CmpUL (compare 2 unsigned longs) node, based on local information.
+// If both inputs are constants, compare them.
+const Type* CmpULNode::sub(const Type* t1, const Type* t2) const {
+  assert(!t1->isa_ptr(), "obsolete usage of CmpUL");
+
+  // comparing two unsigned longs
+  const TypeLong* r0 = t1->is_long();   // Handy access
+  const TypeLong* r1 = t2->is_long();
+
+  // Current installed version
+  // Compare ranges for non-overlap
+  julong lo0 = r0->_lo;
+  julong hi0 = r0->_hi;
+  julong lo1 = r1->_lo;
+  julong hi1 = r1->_hi;
+
+  // If either one has both negative and positive values,
+  // it therefore contains both 0 and -1, and since [0..-1] is the
+  // full unsigned range, the type must act as an unsigned bottom.
+  bool bot0 = ((jlong)(lo0 ^ hi0) < 0);
+  bool bot1 = ((jlong)(lo1 ^ hi1) < 0);
+
+  if (bot0 || bot1) {
+    // All unsigned values are LE -1 and GE 0.
+    if (lo0 == 0 && hi0 == 0) {
+      return TypeInt::CC_LE;            //   0 <= bot
+    } else if ((jlong)lo0 == -1 && (jlong)hi0 == -1) {
+      return TypeInt::CC_GE;            // -1 >= bot
+    } else if (lo1 == 0 && hi1 == 0) {
+      return TypeInt::CC_GE;            // bot >= 0
+    } else if ((jlong)lo1 == -1 && (jlong)hi1 == -1) {
+      return TypeInt::CC_LE;            // bot <= -1
+    }
+  } else {
+    // We can use ranges of the form [lo..hi] if signs are the same.
+    assert(lo0 <= hi0 && lo1 <= hi1, "unsigned ranges are valid");
+    // results are reversed, '-' > '+' for unsigned compare
+    if (hi0 < lo1) {
+      return TypeInt::CC_LT;            // smaller
+    } else if (lo0 > hi1) {
+      return TypeInt::CC_GT;            // greater
+    } else if (hi0 == lo1 && lo0 == hi1) {
+      return TypeInt::CC_EQ;            // Equal results
+    } else if (lo0 >= hi1) {
+      return TypeInt::CC_GE;
+    } else if (hi0 <= lo1) {
+      return TypeInt::CC_LE;
+    }
+  }
+
+  return TypeInt::CC;                   // else use worst case results
+}
+
 //=============================================================================
 //------------------------------sub--------------------------------------------
 // Simplify an CmpP (compare 2 pointers) node, based on local information.
--- a/src/share/vm/opto/subnode.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/opto/subnode.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -198,6 +198,15 @@
   virtual const Type *sub( const Type *, const Type * ) const;
 };
 
+//------------------------------CmpULNode---------------------------------------
+// Compare 2 unsigned long values, returning condition codes (-1, 0 or 1).
+class CmpULNode : public CmpNode {
+public:
+  CmpULNode(Node* in1, Node* in2) : CmpNode(in1, in2) { }
+  virtual int Opcode() const;
+  virtual const Type* sub(const Type*, const Type*) const;
+};
+
 //------------------------------CmpL3Node--------------------------------------
 // Compare 2 long values, returning integer value (-1, 0 or 1).
 class CmpL3Node : public CmpLNode {
--- a/src/share/vm/prims/jvmti.xml	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/prims/jvmti.xml	Wed Aug 02 15:59:33 2017 +0000
@@ -404,7 +404,7 @@
     interfaces are more appropriate than <jvmti/> for many tools.
     For more information on the Java Platform Debugger Architecture,
     see the
-    <externallink id="docs/technotes/guides/jpda/architecture.html">Java
+    <externallink id="jpda/architecture.html">Java
       Platform Debugger Architecture website</externallink>.
   </intro>
 
@@ -10927,7 +10927,7 @@
 	  for a class. The segment is typically a directory or JAR file.
 	  <p/>
 	  In the live phase the <paramlink id="segment"/> may be used to specify any platform-dependent
-	  path to a <externallink id="docs/technotes/guides/jar/jar.html">
+	  path to a <externallink id="jar/jar.html">
 	  JAR file</externallink>. The agent should take care that the JAR file does not
           contain any classes or resources other than those to be defined by the bootstrap
           class loader for the purposes of instrumentation.
@@ -10975,7 +10975,7 @@
 	  for a class. The segment is typically a directory or JAR file.
 	  <p/>
 	  In the live phase the <paramlink id="segment"/> is a platform-dependent path to a
-	  <externallink id="docs/technotes/guides/jar/jar.html">JAR file</externallink> to be
+	  <externallink id="jar/jar.html">JAR file</externallink> to be
 	  searched after the system class loader unsuccessfully searches for a class. The agent should
           take care that the JAR file does not contain any classes or resources other than those to be
           defined by the system class loader for the purposes of instrumentation.
--- a/src/share/vm/prims/jvmti.xsl	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/prims/jvmti.xsl	Wed Aug 02 15:59:33 2017 +0000
@@ -1,6 +1,6 @@
 <?xml version="1.0"?> 
 <!--
- Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -1033,10 +1033,6 @@
 <xsl:template match="externallink">
   <a>
     <xsl:attribute name="href">
-      <!-- All external links start from the same prefix -->
-      <xsl:text>http://docs.oracle.com/javase/</xsl:text>
-      <xsl:value-of select="//specification/@majorversion"/>
-      <xsl:text>/</xsl:text>
       <xsl:value-of select="@id"/>
     </xsl:attribute>
     <xsl:value-of select="."/>
--- a/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -23,14 +23,16 @@
  */
 
 #include "precompiled.hpp"
+#include "code/relocInfo.hpp"
+#include "compiler/compilerDefinitions.hpp"
 #include "oops/metadata.hpp"
 #include "runtime/os.hpp"
-#include "code/relocInfo.hpp"
 #include "interpreter/invocationCounter.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/commandLineFlagConstraintsCompiler.hpp"
 #include "runtime/commandLineFlagRangeList.hpp"
 #include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
 #include "utilities/defaultStream.hpp"
 
 Flag::Error AliasLevelConstraintFunc(intx value, bool verbose) {
--- a/src/share/vm/runtime/commandLineFlagRangeList.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/runtime/commandLineFlagRangeList.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -27,9 +27,11 @@
 #include "classfile/symbolTable.hpp"
 #include "gc/shared/referenceProcessor.hpp"
 #include "prims/jvm.h"
+#include "oops/markOop.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/commandLineFlagConstraintList.hpp"
 #include "runtime/commandLineFlagRangeList.hpp"
+#include "runtime/globals_extension.hpp"
 #include "runtime/os.hpp"
 #include "runtime/task.hpp"
 #include "utilities/defaultStream.hpp"
--- a/src/share/vm/runtime/compilationPolicy.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/runtime/compilationPolicy.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -313,7 +313,7 @@
   // at this point and hence SystemDictionary_lock is also not needed.
   assert(SafepointSynchronize::is_at_safepoint(), "can only be executed at a safepoint");
   int nclasses = InstanceKlass::number_of_instance_classes();
-  double classes_per_tick = nclasses * (CounterDecayMinIntervalLength * 1e-3 /
+  int classes_per_tick = nclasses * (CounterDecayMinIntervalLength * 1e-3 /
                                         CounterHalfLifeTime);
   for (int i = 0; i < classes_per_tick; i++) {
     InstanceKlass* k = ClassLoaderDataGraph::try_get_next_class();
--- a/src/share/vm/runtime/synchronizer.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/runtime/synchronizer.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -1670,7 +1670,7 @@
 // process the same monitor lists concurrently.
 //
 // See also ParallelSPCleanupTask and
-// SafepointSynchronizer::do_cleanup_tasks() in safepoint.cpp and
+// SafepointSynchronize::do_cleanup_tasks() in safepoint.cpp and
 // Threads::parallel_java_threads_do() in thread.cpp.
 int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** listHeadp,
                                              ObjectMonitor** freeHeadp,
--- a/src/share/vm/runtime/thread.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/runtime/thread.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -848,6 +848,13 @@
   }
 }
 
+void Thread::print_value_on(outputStream* st) const {
+  if (is_Named_thread()) {
+    st->print(" \"%s\" ", name());
+  }
+  st->print(INTPTR_FORMAT, p2i(this));   // print address
+}
+
 #ifdef ASSERT
 void Thread::print_owned_locks_on(outputStream* st) const {
   Monitor *cur = _owned_locks;
@@ -3392,6 +3399,13 @@
       tc->do_thread(p);
     }
   }
+  // Thread claiming protocol requires us to claim the same interesting
+  // threads on all paths. Notably, Threads::possibly_parallel_threads_do
+  // claims all Java threads *and* the VMThread. To avoid breaking the
+  // claiming protocol, we have to claim VMThread on this path too, even
+  // if we do not apply the closure to the VMThread.
+  VMThread* vmt = VMThread::vm_thread();
+  (void)vmt->claim_oops_do(true, cp);
 }
 
 // The system initialization in the library has three phases.
@@ -4357,6 +4371,10 @@
     assert((thread_parity == _thread_claim_parity),
            "Thread " PTR_FORMAT " has incorrect parity %d != %d", p2i(p), thread_parity, _thread_claim_parity);
   }
+  VMThread* vmt = VMThread::vm_thread();
+  const int thread_parity = vmt->oops_do_parity();
+  assert((thread_parity == _thread_claim_parity),
+         "VMThread " PTR_FORMAT " has incorrect parity %d != %d", p2i(vmt), thread_parity, _thread_claim_parity);
 }
 #endif // ASSERT
 
--- a/src/share/vm/runtime/thread.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/runtime/thread.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -574,6 +574,7 @@
   virtual void print_on(outputStream* st) const;
   void print() const { print_on(tty); }
   virtual void print_on_error(outputStream* st, char* buf, int buflen) const;
+  void print_value_on(outputStream* st) const;
 
   // Debug-only code
 #ifdef ASSERT
--- a/src/share/vm/runtime/vmStructs.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -32,6 +32,7 @@
 #include "classfile/dictionary.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeBlob.hpp"
 #include "code/codeCache.hpp"
@@ -1944,6 +1945,7 @@
   declare_c2_type(CmpPNode, CmpNode)                                      \
   declare_c2_type(CmpNNode, CmpNode)                                      \
   declare_c2_type(CmpLNode, CmpNode)                                      \
+  declare_c2_type(CmpULNode, CmpNode)                                     \
   declare_c2_type(CmpL3Node, CmpLNode)                                    \
   declare_c2_type(CmpFNode, CmpNode)                                      \
   declare_c2_type(CmpF3Node, CmpFNode)                                    \
--- a/src/share/vm/runtime/vmThread.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/runtime/vmThread.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -25,6 +25,8 @@
 #include "precompiled.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc/shared/collectedHeap.hpp"
+#include "logging/log.hpp"
+#include "logging/logConfiguration.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/method.hpp"
 #include "oops/oop.inline.hpp"
@@ -484,6 +486,7 @@
       // If we are at a safepoint we will evaluate all the operations that
       // follow that also require a safepoint
       if (_cur_vm_operation->evaluate_at_safepoint()) {
+        log_debug(vmthread)("Evaluating safepoint VM operation: %s", _cur_vm_operation->name());
 
         _vm_queue->set_drain_list(safepoint_ops); // ensure ops can be scanned
 
@@ -495,6 +498,7 @@
           _cur_vm_operation = safepoint_ops;
           if (_cur_vm_operation != NULL) {
             do {
+              log_debug(vmthread)("Evaluating coalesced safepoint VM operation: %s", _cur_vm_operation->name());
               // evaluate_operation deletes the op object so we have
               // to grab the next op now
               VM_Operation* next = _cur_vm_operation->next();
@@ -532,6 +536,7 @@
         SafepointSynchronize::end();
 
       } else {  // not a safepoint operation
+        log_debug(vmthread)("Evaluating non-safepoint VM operation: %s", _cur_vm_operation->name());
         if (TraceLongCompiles) {
           elapsedTimer t;
           t.start();
@@ -607,8 +612,9 @@
     // to be queued up during a safepoint synchronization.
     {
       VMOperationQueue_lock->lock_without_safepoint_check();
+      log_debug(vmthread)("Adding VM operation: %s", op->name());
       bool ok = _vm_queue->add(op);
-    op->set_timestamp(os::javaTimeMillis());
+      op->set_timestamp(os::javaTimeMillis());
       VMOperationQueue_lock->notify();
       VMOperationQueue_lock->unlock();
       // VM_Operation got skipped
--- a/src/share/vm/services/diagnosticCommand.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/services/diagnosticCommand.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -84,6 +84,7 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemDictionaryDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHierarchyDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SymboltableDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<StringtableDCmd>(full_export, true, false));
--- a/src/share/vm/services/diagnosticCommand.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/services/diagnosticCommand.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,9 @@
 #ifndef SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
 #define SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
 
+#include "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/os.hpp"
@@ -724,4 +727,116 @@
   virtual void execute(DCmdSource source, TRAPS);
 };
 
+///////////////////////////////////////////////////////////////////////
+//
+// jcmd command support for symbol table, string table and system dictionary dumping:
+//   VM.symboltable -verbose: for dumping the symbol table
+//   VM.stringtable -verbose: for dumping the string table
+//   VM.systemdictionary -verbose: for dumping the system dictionary table
+//
+class VM_DumpHashtable : public VM_Operation {
+private:
+  outputStream* _out;
+  int _which;
+  bool _verbose;
+public:
+  enum {
+    DumpSymbols = 1 << 0,
+    DumpStrings = 1 << 1,
+    DumpSysDict = 1 << 2  // not implemented yet
+  };
+  VM_DumpHashtable(outputStream* out, int which, bool verbose) {
+    _out = out;
+    _which = which;
+    _verbose = verbose;
+  }
+
+  virtual VMOp_Type type() const { return VMOp_DumpHashtable; }
+
+  virtual void doit() {
+    switch (_which) {
+    case DumpSymbols:
+      SymbolTable::dump(_out, _verbose);
+      break;
+    case DumpStrings:
+      StringTable::dump(_out, _verbose);
+      break;
+    case DumpSysDict:
+      SystemDictionary::dump(_out, _verbose);
+      break;
+    default:
+      ShouldNotReachHere();
+    }
+  }
+};
+
+class SymboltableDCmd : public DCmdWithParser {
+protected:
+  DCmdArgument<bool> _verbose;
+public:
+  SymboltableDCmd(outputStream* output, bool heap);
+  static const char* name() {
+    return "VM.symboltable";
+  }
+  static const char* description() {
+    return "Dump symbol table.";
+  }
+  static const char* impact() {
+    return "Medium: Depends on Java content.";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments();
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class StringtableDCmd : public DCmdWithParser {
+protected:
+  DCmdArgument<bool> _verbose;
+public:
+  StringtableDCmd(outputStream* output, bool heap);
+  static const char* name() {
+    return "VM.stringtable";
+  }
+  static const char* description() {
+    return "Dump string table.";
+  }
+  static const char* impact() {
+    return "Medium: Depends on Java content.";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments();
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class SystemDictionaryDCmd : public DCmdWithParser {
+protected:
+  DCmdArgument<bool> _verbose;
+public:
+  SystemDictionaryDCmd(outputStream* output, bool heap);
+  static const char* name() {
+    return "VM.systemdictionary";
+  }
+  static const char* description() {
+    return "Prints the statistics for dictionary hashtable sizes and bucket length";
+  }
+  static const char* impact() {
+      return "Medium: Depends on Java content.";
+  }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+                        "monitor", NULL};
+    return p;
+  }
+  static int num_arguments();
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
 #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/src/share/vm/utilities/hashtable.cpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/utilities/hashtable.cpp	Wed Aug 02 15:59:33 2017 +0000
@@ -231,24 +231,42 @@
   }
 }
 
-template <class T, MEMFLAGS F> int RehashableHashtable<T, F>::literal_size(Symbol *symbol) {
+// For oops and Strings the size of the literal is interesting. For other types, nobody cares.
+static int literal_size(ConstantPool*) { return 0; }
+static int literal_size(Klass*)        { return 0; }
+#if INCLUDE_ALL_GCS
+static int literal_size(nmethod*)      { return 0; }
+#endif
+
+static int literal_size(Symbol *symbol) {
   return symbol->size() * HeapWordSize;
 }
 
-template <class T, MEMFLAGS F> int RehashableHashtable<T, F>::literal_size(oop oop) {
+static int literal_size(oop obj) {
   // NOTE: this would over-count if (pre-JDK8) java_lang_Class::has_offset_field() is true,
   // and the String.value array is shared by several Strings. However, starting from JDK8,
   // the String.value array is not shared anymore.
-  assert(oop != NULL && oop->klass() == SystemDictionary::String_klass(), "only strings are supported");
-  return (oop->size() + java_lang_String::value(oop)->size()) * HeapWordSize;
+  if (obj == NULL) {
+    return 0;
+  } else if (obj->klass() == SystemDictionary::String_klass()) {
+    return (obj->size() + java_lang_String::value(obj)->size()) * HeapWordSize;
+  } else {
+    return obj->size();
+  }
 }
 
+
 // Dump footprint and bucket length statistics
 //
 // Note: if you create a new subclass of Hashtable<MyNewType, F>, you will need to
-// add a new function Hashtable<T, F>::literal_size(MyNewType lit)
+// add a new function static int literal_size(MyNewType lit)
+// because I can't get template <class T> int literal_size(T) to pick the specializations for Symbol and oop.
+//
+// The StringTable and SymbolTable dumping print how much footprint is used by the String and Symbol
+// literals.
 
-template <class T, MEMFLAGS F> void RehashableHashtable<T, F>::dump_table(outputStream* st, const char *table_name) {
+template <class T, MEMFLAGS F> void Hashtable<T, F>::print_table_statistics(outputStream* st,
+                                                                            const char *table_name) {
   NumberSeq summary;
   int literal_bytes = 0;
   for (int i = 0; i < this->table_size(); ++i) {
@@ -267,14 +285,16 @@
   int entry_bytes  = (int)num_entries * sizeof(HashtableEntry<T, F>);
   int total_bytes = literal_bytes +  bucket_bytes + entry_bytes;
 
-  double bucket_avg  = (num_buckets <= 0) ? 0 : (bucket_bytes  / num_buckets);
-  double entry_avg   = (num_entries <= 0) ? 0 : (entry_bytes   / num_entries);
-  double literal_avg = (num_entries <= 0) ? 0 : (literal_bytes / num_entries);
+  int bucket_size  = (num_buckets <= 0) ? 0 : (bucket_bytes  / num_buckets);
+  int entry_size   = (num_entries <= 0) ? 0 : (entry_bytes   / num_entries);
 
   st->print_cr("%s statistics:", table_name);
-  st->print_cr("Number of buckets       : %9d = %9d bytes, avg %7.3f", (int)num_buckets, bucket_bytes,  bucket_avg);
-  st->print_cr("Number of entries       : %9d = %9d bytes, avg %7.3f", (int)num_entries, entry_bytes,   entry_avg);
-  st->print_cr("Number of literals      : %9d = %9d bytes, avg %7.3f", (int)num_entries, literal_bytes, literal_avg);
+  st->print_cr("Number of buckets       : %9d = %9d bytes, each %d", (int)num_buckets, bucket_bytes,  bucket_size);
+  st->print_cr("Number of entries       : %9d = %9d bytes, each %d", (int)num_entries, entry_bytes,   entry_size);
+  if (literal_bytes != 0) {
+    double literal_avg = (num_entries <= 0) ? 0 : (literal_bytes / num_entries);
+    st->print_cr("Number of literals      : %9d = %9d bytes, avg %7.3f", (int)num_entries, literal_bytes, literal_avg);
+  }
   st->print_cr("Total footprint         : %9s = %9d bytes", "", total_bytes);
   st->print_cr("Average bucket size     : %9.3f", summary.avg());
   st->print_cr("Variance of bucket size : %9.3f", summary.variance());
@@ -300,7 +320,6 @@
   *top += len;
 }
 
-
 #ifndef PRODUCT
 
 template <class T, MEMFLAGS F> void Hashtable<T, F>::print() {
@@ -398,4 +417,3 @@
 template void BasicHashtable<mtModule>::verify_table<PackageEntry>(char const*);
 template void BasicHashtable<mtClass>::verify_table<ProtectionDomainCacheEntry>(char const*);
 template void BasicHashtable<mtClass>::verify_table<PlaceholderEntry>(char const*);
-
--- a/src/share/vm/utilities/hashtable.hpp	Wed Aug 02 08:53:18 2017 -0700
+++ b/src/share/vm/utilities/hashtable.hpp	Wed Aug 02 15:59:33 2017 +0000
@@ -226,14 +226,14 @@
   // is mt-safe wrt. to other calls of this method.
   void bulk_free_entries(BucketUnlinkContext* context);
 public:
-  int table_size() { return _table_size; }
+  int table_size() const { return _table_size; }
   void set_entry(int index, BasicHashtableEntry<F>* entry);
 
   void add_entry(int index, BasicHashtableEntry<F>* entry);
 
   void free_entry(BasicHashtableEntry<F>* entry);
 
-  int number_of_entries() { return _number_of_entries; }
+  int number_of_entries() const { return _number_of_entries; }
 
   template <class T> void verify_table(const char* table_name) PRODUCT_RETURN;
 };
@@ -261,7 +261,9 @@
     return this->hash_to_index(compute_hash(name));
   }
 
-protected:
+  void print_table_statistics(outputStream* st, const char *table_name);
+
+ protected:
 
   // Table entry management
   HashtableEntry<T, F>* new_entry(unsigned int hashValue, T obj);
@@ -306,18 +308,6 @@
   static bool use_alternate_hashcode();
   static juint seed();
 
-  static int literal_size(Symbol *symbol);
-  static int literal_size(oop oop);
-
-  // The following two are currently not used, but are needed anyway because some
-  // C++ compilers (MacOS and Solaris) force the instantiation of
-  // Hashtable<ConstantPool*, mtClass>::dump_table() even though we never call this function
-  // in the VM code.
-  static int literal_size(ConstantPool *cp) {Unimplemented(); return 0;}
-  static int literal_size(Klass *k)         {Unimplemented(); return 0;}
-
-  void dump_table(outputStream* st, const char *table_name);
-
  private:
   static juint _seed;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/arraycopy/TestLoadBypassACWithWrongMem.java	Wed Aug 02 15:59:33 2017 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8181742
+ * @summary Loads that bypass arraycopy ends up with wrong memory state
+ *
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+StressGCM -XX:+StressLCM TestLoadBypassACWithWrongMem
+ *
+ */
+
+import java.util.Arrays;
+
+public class TestLoadBypassACWithWrongMem {
+
+    static int test1(int[] src) {
+        int[] dst = new int[10];
+        System.arraycopy(src, 0, dst, 0, 10);
+        src[1] = 0x42;
+        // dst[1] is transformed to src[1], src[1] must use the
+        // correct memory state (not the store above).
+        return dst[1];
+    }
+
+    static int test2(int[] src) {
+        int[] dst = (int[])src.clone();
+        src[1] = 0x42;
+        // Same as above for clone
+        return dst[1];
+    }
+
+    static Object test5_src = null;
+    static int test3() {
+        int[] dst = new int[10];
+        System.arraycopy(test5_src, 0, dst, 0, 10);
+        ((int[])test5_src)[1] = 0x42;
+        System.arraycopy(test5_src, 0, dst, 0, 10);
+        // dst[1] is transformed to test5_src[1]. test5_src is Object
+        // but test5_src[1] must be on the slice for int[] not
+        // Object+some offset.
+        return dst[1];
+    }
+
+    static public void main(String[] args) {
+        int[] src = new int[10];
+        for (int i = 0; i < 20000; i++) {
+            Arrays.fill(src, 0);
+            int res = test1(src);
+            if (res != 0) {
+                throw new RuntimeException("bad result: " + res + " != " + 0);
+            }
+            Arrays.fill(src, 0);
+            res = test2(src);
+            if (res != 0) {
+                throw new RuntimeException("bad result: " + res + " != " + 0);
+            }
+            Arrays.fill(src, 0);
+            test5_src = src;
+            res = test3();
+            if (res != 0x42) {
+                throw new RuntimeException("bad result: " + res + " != " + 0x42);
+            }
+         }
+    }
+}
--- a/test/compiler/rangechecks/TestRangeCheckEliminationDisabled.java	Wed Aug 02 08:53:18 2017 -0700
+++ b/test/compiler/rangechecks/TestRangeCheckEliminationDisabled.java	Wed Aug 02 15:59:33 2017 +0000
@@ -26,7 +26,7 @@
  * @bug 8154763
  * @summary Tests PostLoopMultiversioning with RangeCheckElimination disabled.
  * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- *                   -XX:+PostLoopMultiversioning -XX:-RangeCheckElimination
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+PostLoopMultiversioning -XX:-RangeCheckElimination
  *                   compiler.rangechecks.TestRangeCheckEliminationDisabled
  */
 
--- a/test/gc/TestFullGCALot.java	Wed Aug 02 08:53:18 2017 -0700
+++ b/test/gc/TestFullGCALot.java	Wed Aug 02 15:59:33 2017 +0000
@@ -25,9 +25,9 @@
  * @test TestFullGCALot
  * @key gc
  * @bug 4187687
- * @summary Ensure no acess violation when using FullGCALot
+ * @summary Ensure no access violation when using FullGCALot
  * @requires vm.debug
- * @run main/othervm -XX:+FullGCALot -XX:FullGCALotInterval=120 TestFullGCALot
+ * @run main/othervm -XX:NewSize=10m -XX:+FullGCALot -XX:FullGCALotInterval=120 TestFullGCALot
  */
 
 public class TestFullGCALot {
--- a/test/gc/stress/systemgc/TestSystemGC.java	Wed Aug 02 08:53:18 2017 -0700
+++ b/test/gc/stress/systemgc/TestSystemGC.java	Wed Aug 02 15:59:33 2017 +0000
@@ -182,9 +182,11 @@
     }
 
     public static void main(String[] args) {
-        // First allocate the long lived objects and then run all phases twice.
+        // First allocate the long lived objects and then run all phases.
         populateLongLived();
         runAllPhases();
-        runAllPhases();
+        if (args.length > 0 && args[0].equals("long")) {
+            runAllPhases();
+        }
     }
 }
--- a/test/runtime/SharedArchiveFile/DumpSymbolAndStringTable.java	Wed Aug 02 08:53:18 2017 -0700
+++ b/test/runtime/SharedArchiveFile/DumpSymbolAndStringTable.java	Wed Aug 02 15:59:33 2017 +0000
@@ -56,5 +56,25 @@
         } catch (RuntimeException e) {
             output.shouldContain("Unknown diagnostic command");
         }
+
+        pb.command(new String[] {JDKToolFinder.getJDKTool("jcmd"), pid, "VM.systemdictionary"});
+        output = CDSTestUtils.executeAndLog(pb, "jcmd-systemdictionary");
+        try {
+            output.shouldContain("System Dictionary for jdk/internal/loader/ClassLoaders$AppClassLoader statistics:");
+            output.shouldContain("Number of buckets");
+            output.shouldContain("Number of entries");
+            output.shouldContain("Maximum bucket size");
+        } catch (RuntimeException e) {
+            output.shouldContain("Unknown diagnostic command");
+        }
+
+        pb.command(new String[] {JDKToolFinder.getJDKTool("jcmd"), pid, "VM.systemdictionary", "-verbose"});
+        output = CDSTestUtils.executeAndLog(pb, "jcmd-systemdictionary");
+        try {
+            output.shouldContain("Dictionary for class loader 0x");
+            output.shouldContain("^java.lang.String");
+        } catch (RuntimeException e) {
+            output.shouldContain("Unknown diagnostic command");
+        }
     }
 }