changeset 13529:958228979fe8 mvt

Merge
author dsimms
date Thu, 24 Aug 2017 09:44:52 +0200
parents f017570123b2 9a75c2f7bf06
children a91fe71f54e7
files src/cpu/aarch64/vm/globals_aarch64.hpp src/cpu/x86/vm/globals_x86.hpp src/cpu/x86/vm/interp_masm_x86.cpp src/cpu/x86/vm/x86_64.ad src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderTable.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainCacheEntry.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainEntry.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/TwoOopHashtable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayDuplicationBenchmark.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayListBenchmark.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/BoxingBenchmark.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ConcurrentSkipListBenchmark.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/GuardedIntrinsicBenchmark.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/HashBenchmark.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/MathFunctionBenchmark.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/SimpleSyncBenchmark.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/package-info.java src/os_cpu/solaris_x86/vm/solaris_x86_32.il src/os_cpu/solaris_x86/vm/solaris_x86_32.s src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/classLoaderData.cpp src/share/vm/classfile/classLoaderData.hpp src/share/vm/classfile/javaClasses.cpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.cpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/code/compiledMethod.cpp src/share/vm/gc/g1/workerDataArray.cpp src/share/vm/gc/g1/workerDataArray.hpp src/share/vm/gc/g1/workerDataArray.inline.hpp src/share/vm/gc/parallel/psParallelCompact.cpp src/share/vm/gc/serial/markSweep.cpp src/share/vm/interpreter/rewriter.cpp src/share/vm/jvmci/jvmciCompilerToVM.cpp src/share/vm/logging/logTag.hpp src/share/vm/memory/allocation.hpp src/share/vm/oops/arrayKlass.cpp src/share/vm/oops/arrayKlass.hpp src/share/vm/oops/constantPool.cpp src/share/vm/oops/constantPool.hpp src/share/vm/oops/cpCache.cpp src/share/vm/oops/cpCache.hpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp src/share/vm/oops/klass.hpp src/share/vm/oops/klassVtable.cpp src/share/vm/oops/klassVtable.hpp src/share/vm/oops/method.cpp src/share/vm/oops/method.hpp src/share/vm/oops/methodData.cpp src/share/vm/oops/objArrayKlass.cpp src/share/vm/oops/objArrayKlass.hpp src/share/vm/oops/oop.cpp src/share/vm/oops/oop.hpp src/share/vm/oops/oop.inline.hpp src/share/vm/opto/classes.hpp src/share/vm/opto/compile.cpp src/share/vm/opto/doCall.cpp src/share/vm/opto/library_call.cpp src/share/vm/opto/macroArrayCopy.cpp src/share/vm/opto/memnode.cpp src/share/vm/opto/memnode.hpp src/share/vm/opto/output.cpp src/share/vm/precompiled/precompiled.hpp src/share/vm/prims/whitebox.cpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/globals.hpp src/share/vm/runtime/handles.hpp src/share/vm/runtime/reflection.cpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp src/share/vm/runtime/vmStructs.cpp src/share/vm/services/diagnosticCommand.cpp src/share/vm/services/diagnosticCommand.hpp src/share/vm/utilities/globalDefinitions.hpp test/native/gc/g1/test_workerDataArray.cpp test/runtime/SharedArchiveFile/LargeSharedSpace.java test/runtime/SharedArchiveFile/LimitSharedSizes.java
diffstat 568 files changed, 15088 insertions(+), 9583 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Aug 21 14:05:14 2017 +0200
+++ b/.hgtags	Thu Aug 24 09:44:52 2017 +0200
@@ -592,3 +592,15 @@
 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
+c9d3317623d48da3327232c81e3f8cfc0d29d888 jdk-10+18
+33b74e13c1457f36041addb8b850831f81ca6e9f jdk-10+19
+d7baadc223e790c08bc69bf7e553bce65b4e7e40 jdk-9+180
+4a443796f6f57842d6a0434ac27ca3d1033ccc20 jdk-9+181
--- a/make/test/JtregNative.gmk	Mon Aug 21 14:05:14 2017 +0200
+++ b/make/test/JtregNative.gmk	Thu Aug 24 09:44:52 2017 +0200
@@ -61,6 +61,7 @@
     $(HOTSPOT_TOPDIR)/test/runtime/noClassDefFoundMsg \
     $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
     $(HOTSPOT_TOPDIR)/test/compiler/calls \
+    $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetOwnedMonitorInfo \
     $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetNamedModule \
     $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/IsModifiableModule \
     $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/AddModuleReads \
@@ -92,6 +93,7 @@
 ifeq ($(TOOLCHAIN_TYPE), solstudio)
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liboverflow := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSimpleClassFileLoadHook := -lc
+    BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetOwnedMonitorInfoTest := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetNamedModuleTest := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libIsModifiableModuleTest := -lc
     BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libAddModuleReadsTest := -lc
--- a/src/cpu/aarch64/vm/aarch64.ad	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/aarch64.ad	Thu Aug 24 09:44:52 2017 +0200
@@ -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);
@@ -16046,6 +16102,16 @@
   ins_pipe(pipe_class_memory);
 %}
 
+instruct has_negatives(iRegP_R1 ary1, iRegI_R2 len, iRegI_R0 result, rFlagsReg cr)
+%{
+  match(Set result (HasNegatives ary1 len));
+  effect(USE_KILL ary1, USE_KILL len, KILL cr);
+  format %{ "has negatives byte[] $ary1,$len -> $result" %}
+  ins_encode %{
+    __ has_negatives($ary1$$Register, $len$$Register, $result$$Register);
+  %}
+  ins_pipe( pipe_slow );
+%}
 
 // fast char[] to byte[] compression
 instruct string_compress(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len,
--- a/src/cpu/aarch64/vm/c2_globals_aarch64.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/c2_globals_aarch64.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -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/aarch64/vm/globals_aarch64.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/globals_aarch64.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -156,8 +156,11 @@
   product(intx, BlockZeroingLowLimit, 256,                              \
           "Minimum size in bytes when block zeroing will be used")      \
           range(1, max_jint)                                            \
-  product(bool, TraceTraps, false, "Trace all traps the signal handler")
-
+  product(bool, TraceTraps, false, "Trace all traps the signal handler")\
+  product(int, SoftwarePrefetchHintDistance, -1,                        \
+          "Use prfm hint with specified distance in compiled code."     \
+          "Value -1 means off.")                                        \
+          range(-1, 32760)
 #endif
 
 
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -4829,6 +4829,62 @@
   BLOCK_COMMENT("} string_compare");
 }
 
+// This method checks if provided byte array contains byte with highest bit set.
+void MacroAssembler::has_negatives(Register ary1, Register len, Register result) {
+    // Simple and most common case of aligned small array which is not at the
+    // end of memory page is placed here. All other cases are in stub.
+    Label LOOP, END, STUB, STUB_LONG, SET_RESULT, DONE;
+    const uint64_t UPPER_BIT_MASK=0x8080808080808080;
+    assert_different_registers(ary1, len, result);
+
+    cmpw(len, 0);
+    br(LE, SET_RESULT);
+    cmpw(len, 4 * wordSize);
+    br(GE, STUB_LONG); // size > 32 then go to stub
+
+    int shift = 64 - exact_log2(os::vm_page_size());
+    lsl(rscratch1, ary1, shift);
+    mov(rscratch2, (size_t)(4 * wordSize) << shift);
+    adds(rscratch2, rscratch1, rscratch2);  // At end of page?
+    br(CS, STUB); // at the end of page then go to stub
+    subs(len, len, wordSize);
+    br(LT, END);
+
+  BIND(LOOP);
+    ldr(rscratch1, Address(post(ary1, wordSize)));
+    tst(rscratch1, UPPER_BIT_MASK);
+    br(NE, SET_RESULT);
+    subs(len, len, wordSize);
+    br(GE, LOOP);
+    cmpw(len, -wordSize);
+    br(EQ, SET_RESULT);
+
+  BIND(END);
+    ldr(result, Address(ary1));
+    sub(len, zr, len, LSL, 3); // LSL 3 is to get bits from bytes
+    lslv(result, result, len);
+    tst(result, UPPER_BIT_MASK);
+    b(SET_RESULT);
+
+  BIND(STUB);
+    RuntimeAddress has_neg =  RuntimeAddress(StubRoutines::aarch64::has_negatives());
+    assert(has_neg.target() != NULL, "has_negatives stub has not been generated");
+    trampoline_call(has_neg);
+    b(DONE);
+
+  BIND(STUB_LONG);
+    RuntimeAddress has_neg_long =  RuntimeAddress(
+            StubRoutines::aarch64::has_negatives_long());
+    assert(has_neg_long.target() != NULL, "has_negatives stub has not been generated");
+    trampoline_call(has_neg_long);
+    b(DONE);
+
+  BIND(SET_RESULT);
+    cset(result, NE); // set true or false
+
+  BIND(DONE);
+}
+
 // Compare Strings or char/byte arrays.
 
 // is_string is true iff this is a string comparison.
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -1210,6 +1210,8 @@
                       Register tmp1,
                       FloatRegister vtmp, FloatRegister vtmpZ, int ae);
 
+  void has_negatives(Register ary1, Register len, Register result);
+
   void arrays_equals(Register a1, Register a2,
                      Register result, Register cnt1,
                      int elem_size, bool is_string);
--- a/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -3670,6 +3670,167 @@
     __ eor(result, __ T16B, lo, t0);
   }
 
+  address generate_has_negatives(address &has_negatives_long) {
+    StubCodeMark mark(this, "StubRoutines", "has_negatives");
+    const int large_loop_size = 64;
+    const uint64_t UPPER_BIT_MASK=0x8080808080808080;
+    int dcache_line = VM_Version::dcache_line_size();
+
+    Register ary1 = r1, len = r2, result = r0;
+
+    __ align(CodeEntryAlignment);
+    address entry = __ pc();
+
+    __ enter();
+
+  Label RET_TRUE, RET_TRUE_NO_POP, RET_FALSE, ALIGNED, LOOP16, CHECK_16, DONE,
+        LARGE_LOOP, POST_LOOP16, LEN_OVER_15, LEN_OVER_8, POST_LOOP16_LOAD_TAIL;
+
+  __ cmp(len, 15);
+  __ br(Assembler::GT, LEN_OVER_15);
+  // The only case when execution falls into this code is when pointer is near
+  // the end of memory page and we have to avoid reading next page
+  __ add(ary1, ary1, len);
+  __ subs(len, len, 8);
+  __ br(Assembler::GT, LEN_OVER_8);
+  __ ldr(rscratch2, Address(ary1, -8));
+  __ sub(rscratch1, zr, len, __ LSL, 3);  // LSL 3 is to get bits from bytes.
+  __ lsrv(rscratch2, rscratch2, rscratch1);
+  __ tst(rscratch2, UPPER_BIT_MASK);
+  __ cset(result, Assembler::NE);
+  __ leave();
+  __ ret(lr);
+  __ bind(LEN_OVER_8);
+  __ ldp(rscratch1, rscratch2, Address(ary1, -16));
+  __ sub(len, len, 8); // no data dep., then sub can be executed while loading
+  __ tst(rscratch2, UPPER_BIT_MASK);
+  __ br(Assembler::NE, RET_TRUE_NO_POP);
+  __ sub(rscratch2, zr, len, __ LSL, 3); // LSL 3 is to get bits from bytes
+  __ lsrv(rscratch1, rscratch1, rscratch2);
+  __ tst(rscratch1, UPPER_BIT_MASK);
+  __ cset(result, Assembler::NE);
+  __ leave();
+  __ ret(lr);
+
+  Register tmp1 = r3, tmp2 = r4, tmp3 = r5, tmp4 = r6, tmp5 = r7, tmp6 = r10;
+  const RegSet spilled_regs = RegSet::range(tmp1, tmp5) + tmp6;
+
+  has_negatives_long = __ pc(); // 2nd entry point
+
+  __ enter();
+
+  __ bind(LEN_OVER_15);
+    __ push(spilled_regs, sp);
+    __ andr(rscratch2, ary1, 15); // check pointer for 16-byte alignment
+    __ cbz(rscratch2, ALIGNED);
+    __ ldp(tmp6, tmp1, Address(ary1));
+    __ mov(tmp5, 16);
+    __ sub(rscratch1, tmp5, rscratch2); // amount of bytes until aligned address
+    __ add(ary1, ary1, rscratch1);
+    __ sub(len, len, rscratch1);
+    __ orr(tmp6, tmp6, tmp1);
+    __ tst(tmp6, UPPER_BIT_MASK);
+    __ br(Assembler::NE, RET_TRUE);
+
+  __ bind(ALIGNED);
+    __ cmp(len, large_loop_size);
+    __ br(Assembler::LT, CHECK_16);
+    // Perform 16-byte load as early return in pre-loop to handle situation
+    // when initially aligned large array has negative values at starting bytes,
+    // so LARGE_LOOP would do 4 reads instead of 1 (in worst case), which is
+    // slower. Cases with negative bytes further ahead won't be affected that
+    // much. In fact, it'll be faster due to early loads, less instructions and
+    // less branches in LARGE_LOOP.
+    __ ldp(tmp6, tmp1, Address(__ post(ary1, 16)));
+    __ sub(len, len, 16);
+    __ orr(tmp6, tmp6, tmp1);
+    __ tst(tmp6, UPPER_BIT_MASK);
+    __ br(Assembler::NE, RET_TRUE);
+    __ cmp(len, large_loop_size);
+    __ br(Assembler::LT, CHECK_16);
+
+    if (SoftwarePrefetchHintDistance >= 0
+        && SoftwarePrefetchHintDistance >= dcache_line) {
+      // initial prefetch
+      __ prfm(Address(ary1, SoftwarePrefetchHintDistance - dcache_line));
+    }
+  __ bind(LARGE_LOOP);
+    if (SoftwarePrefetchHintDistance >= 0) {
+      __ prfm(Address(ary1, SoftwarePrefetchHintDistance));
+    }
+    // Issue load instructions first, since it can save few CPU/MEM cycles, also
+    // instead of 4 triples of "orr(...), addr(...);cbnz(...);" (for each ldp)
+    // better generate 7 * orr(...) + 1 andr(...) + 1 cbnz(...) which saves 3
+    // instructions per cycle and have less branches, but this approach disables
+    // early return, thus, all 64 bytes are loaded and checked every time.
+    __ ldp(tmp2, tmp3, Address(ary1));
+    __ ldp(tmp4, tmp5, Address(ary1, 16));
+    __ ldp(rscratch1, rscratch2, Address(ary1, 32));
+    __ ldp(tmp6, tmp1, Address(ary1, 48));
+    __ add(ary1, ary1, large_loop_size);
+    __ sub(len, len, large_loop_size);
+    __ orr(tmp2, tmp2, tmp3);
+    __ orr(tmp4, tmp4, tmp5);
+    __ orr(rscratch1, rscratch1, rscratch2);
+    __ orr(tmp6, tmp6, tmp1);
+    __ orr(tmp2, tmp2, tmp4);
+    __ orr(rscratch1, rscratch1, tmp6);
+    __ orr(tmp2, tmp2, rscratch1);
+    __ tst(tmp2, UPPER_BIT_MASK);
+    __ br(Assembler::NE, RET_TRUE);
+    __ cmp(len, large_loop_size);
+    __ br(Assembler::GE, LARGE_LOOP);
+
+  __ bind(CHECK_16); // small 16-byte load pre-loop
+    __ cmp(len, 16);
+    __ br(Assembler::LT, POST_LOOP16);
+
+  __ bind(LOOP16); // small 16-byte load loop
+    __ ldp(tmp2, tmp3, Address(__ post(ary1, 16)));
+    __ sub(len, len, 16);
+    __ orr(tmp2, tmp2, tmp3);
+    __ tst(tmp2, UPPER_BIT_MASK);
+    __ br(Assembler::NE, RET_TRUE);
+    __ cmp(len, 16);
+    __ br(Assembler::GE, LOOP16); // 16-byte load loop end
+
+  __ bind(POST_LOOP16); // 16-byte aligned, so we can read unconditionally
+    __ cmp(len, 8);
+    __ br(Assembler::LE, POST_LOOP16_LOAD_TAIL);
+    __ ldr(tmp3, Address(__ post(ary1, 8)));
+    __ sub(len, len, 8);
+    __ tst(tmp3, UPPER_BIT_MASK);
+    __ br(Assembler::NE, RET_TRUE);
+
+  __ bind(POST_LOOP16_LOAD_TAIL);
+    __ cbz(len, RET_FALSE); // Can't shift left by 64 when len==0
+    __ ldr(tmp1, Address(ary1));
+    __ mov(tmp2, 64);
+    __ sub(tmp4, tmp2, len, __ LSL, 3);
+    __ lslv(tmp1, tmp1, tmp4);
+    __ tst(tmp1, UPPER_BIT_MASK);
+    __ br(Assembler::NE, RET_TRUE);
+    // Fallthrough
+
+  __ bind(RET_FALSE);
+    __ pop(spilled_regs, sp);
+    __ leave();
+    __ mov(result, zr);
+    __ ret(lr);
+
+  __ bind(RET_TRUE);
+    __ pop(spilled_regs, sp);
+  __ bind(RET_TRUE_NO_POP);
+    __ leave();
+    __ mov(result, 1);
+    __ ret(lr);
+
+  __ bind(DONE);
+    __ pop(spilled_regs, sp);
+    __ leave();
+    __ ret(lr);
+    return entry;
+  }
   /**
    *  Arguments:
    *
@@ -4686,6 +4847,7 @@
     // }
   };
 
+
   // Initialization
   void generate_initial() {
     // Generate initial stubs and initializes the entry points
@@ -4744,6 +4906,9 @@
     // arraycopy stubs used by compilers
     generate_arraycopy_stubs();
 
+    // has negatives stub for large arrays.
+    StubRoutines::aarch64::_has_negatives = generate_has_negatives(StubRoutines::aarch64::_has_negatives_long);
+
     if (UseMultiplyToLenIntrinsic) {
       StubRoutines::_multiplyToLen = generate_multiplyToLen();
     }
--- a/src/cpu/aarch64/vm/stubRoutines_aarch64.cpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/stubRoutines_aarch64.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -44,6 +44,8 @@
 address StubRoutines::aarch64::_double_sign_mask = NULL;
 address StubRoutines::aarch64::_double_sign_flip = NULL;
 address StubRoutines::aarch64::_zero_blocks = NULL;
+address StubRoutines::aarch64::_has_negatives = NULL;
+address StubRoutines::aarch64::_has_negatives_long = NULL;
 bool StubRoutines::aarch64::_completed = false;
 
 /**
--- a/src/cpu/aarch64/vm/stubRoutines_aarch64.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/stubRoutines_aarch64.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -62,6 +62,9 @@
   static address _double_sign_flip;
 
   static address _zero_blocks;
+
+  static address _has_negatives;
+  static address _has_negatives_long;
   static bool _completed;
 
  public:
@@ -120,6 +123,14 @@
     return _zero_blocks;
   }
 
+  static address has_negatives() {
+    return _has_negatives;
+  }
+
+  static address has_negatives_long() {
+      return _has_negatives_long;
+  }
+
   static bool complete() {
     return _completed;
   }
--- a/src/cpu/aarch64/vm/vm_version_aarch64.cpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/aarch64/vm/vm_version_aarch64.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -137,6 +137,8 @@
     FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 3*dcache_line);
   if (FLAG_IS_DEFAULT(PrefetchCopyIntervalInBytes))
     FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 3*dcache_line);
+  if (FLAG_IS_DEFAULT(SoftwarePrefetchHintDistance))
+    FLAG_SET_DEFAULT(SoftwarePrefetchHintDistance, 3*dcache_line);
 
   if (PrefetchCopyIntervalInBytes != -1 &&
        ((PrefetchCopyIntervalInBytes & 7) || (PrefetchCopyIntervalInBytes >= 32768))) {
@@ -146,6 +148,12 @@
       PrefetchCopyIntervalInBytes = 32760;
   }
 
+  if (SoftwarePrefetchHintDistance != -1 &&
+       (SoftwarePrefetchHintDistance & 7)) {
+    warning("SoftwarePrefetchHintDistance must be -1, or a multiple of 8");
+    SoftwarePrefetchHintDistance &= ~7;
+  }
+
   unsigned long auxv = getauxval(AT_HWCAP);
 
   char buf[512];
--- a/src/cpu/arm/vm/arm.ad	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/arm/vm/arm.ad	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/arm/vm/c2_globals_arm.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -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/assembler_ppc.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/ppc/vm/assembler_ppc.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -510,8 +510,13 @@
     LXVD2X_OPCODE  = (31u << OPCODE_SHIFT |  844u << 1),
     STXVD2X_OPCODE = (31u << OPCODE_SHIFT |  972u << 1),
     MTVSRD_OPCODE  = (31u << OPCODE_SHIFT |  179u << 1),
+    MTVSRWZ_OPCODE = (31u << OPCODE_SHIFT |  243u << 1),
     MFVSRD_OPCODE  = (31u << OPCODE_SHIFT |   51u << 1),
     MTVSRWA_OPCODE = (31u << OPCODE_SHIFT |  211u << 1),
+    MFVSRWZ_OPCODE = (31u << OPCODE_SHIFT |  115u << 1),
+    XXPERMDI_OPCODE= (60u << OPCODE_SHIFT |   10u << 3),
+    XXMRGHW_OPCODE = (60u << OPCODE_SHIFT |   18u << 3),
+    XXMRGLW_OPCODE = (60u << OPCODE_SHIFT |   50u << 3),
 
     // Vector Permute and Formatting
     VPKPX_OPCODE   = (4u  << OPCODE_SHIFT |  782u     ),
@@ -561,6 +566,7 @@
     VADDUBM_OPCODE = (4u  << OPCODE_SHIFT |    0u     ),
     VADDUWM_OPCODE = (4u  << OPCODE_SHIFT |  128u     ),
     VADDUHM_OPCODE = (4u  << OPCODE_SHIFT |   64u     ),
+    VADDUDM_OPCODE = (4u  << OPCODE_SHIFT |  192u     ),
     VADDUBS_OPCODE = (4u  << OPCODE_SHIFT |  512u     ),
     VADDUWS_OPCODE = (4u  << OPCODE_SHIFT |  640u     ),
     VADDUHS_OPCODE = (4u  << OPCODE_SHIFT |  576u     ),
@@ -1099,16 +1105,19 @@
   static int vrs(   VectorRegister r)  { return  vrs(r->encoding());}
   static int vrt(   VectorRegister r)  { return  vrt(r->encoding());}
 
+  // Only used on SHA sigma instructions (VX-form)
+  static int vst(      int         x)  { return  opp_u_field(x,             16, 16); }
+  static int vsix(     int         x)  { return  opp_u_field(x,             20, 17); }
+
   // Support Vector-Scalar (VSX) instructions.
-  static int vsra(      int         x)  { return  opp_u_field(x,            15, 11); }
-  static int vsrb(      int         x)  { return  opp_u_field(x,            20, 16); }
-  static int vsrc(      int         x)  { return  opp_u_field(x,            25, 21); }
-  static int vsrs(      int         x)  { return  opp_u_field(x,            10,  6); }
-  static int vsrt(      int         x)  { return  opp_u_field(x,            10,  6); }
+  static int vsra(      int         x)  { return  opp_u_field(x & 0x1F,     15, 11) | opp_u_field((x & 0x20) >> 5, 29, 29); }
+  static int vsrb(      int         x)  { return  opp_u_field(x & 0x1F,     20, 16) | opp_u_field((x & 0x20) >> 5, 30, 30); }
+  static int vsrs(      int         x)  { return  opp_u_field(x & 0x1F,     10,  6) | opp_u_field((x & 0x20) >> 5, 31, 31); }
+  static int vsrt(      int         x)  { return  vsrs(x); }
+  static int vsdm(      int         x)  { return  opp_u_field(x,            23, 22); }
 
   static int vsra(   VectorSRegister r)  { return  vsra(r->encoding());}
   static int vsrb(   VectorSRegister r)  { return  vsrb(r->encoding());}
-  static int vsrc(   VectorSRegister r)  { return  vsrc(r->encoding());}
   static int vsrs(   VectorSRegister r)  { return  vsrs(r->encoding());}
   static int vsrt(   VectorSRegister r)  { return  vsrt(r->encoding());}
 
@@ -2027,7 +2036,7 @@
   inline void vperm(    VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c);
   inline void vsel(     VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c);
   inline void vsl(      VectorRegister d, VectorRegister a, VectorRegister b);
-  inline void vsldoi(   VectorRegister d, VectorRegister a, VectorRegister b, int si4);
+  inline void vsldoi(   VectorRegister d, VectorRegister a, VectorRegister b, int ui4);
   inline void vslo(     VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vsr(      VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vsro(     VectorRegister d, VectorRegister a, VectorRegister b);
@@ -2038,6 +2047,7 @@
   inline void vaddubm(  VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vadduwm(  VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vadduhm(  VectorRegister d, VectorRegister a, VectorRegister b);
+  inline void vaddudm(  VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vaddubs(  VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vadduws(  VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vadduhs(  VectorRegister d, VectorRegister a, VectorRegister b);
@@ -2113,6 +2123,7 @@
   inline void vandc(    VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vnor(     VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vor(      VectorRegister d, VectorRegister a, VectorRegister b);
+  inline void vmr(      VectorRegister d, VectorRegister a);
   inline void vxor(     VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vrld(     VectorRegister d, VectorRegister a, VectorRegister b);
   inline void vrlb(     VectorRegister d, VectorRegister a, VectorRegister b);
@@ -2136,8 +2147,19 @@
   inline void lxvd2x(   VectorSRegister d, Register a, Register b);
   inline void stxvd2x(  VectorSRegister d, Register a);
   inline void stxvd2x(  VectorSRegister d, Register a, Register b);
+  inline void mtvrwz(   VectorRegister  d, Register a);
+  inline void mfvrwz(   Register        a, VectorRegister d);
   inline void mtvrd(    VectorRegister  d, Register a);
   inline void mfvrd(    Register        a, VectorRegister d);
+  inline void xxpermdi( VectorSRegister d, VectorSRegister a, VectorSRegister b, int dm);
+  inline void xxmrghw(  VectorSRegister d, VectorSRegister a, VectorSRegister b);
+  inline void xxmrglw(  VectorSRegister d, VectorSRegister a, VectorSRegister b);
+
+  // VSX Extended Mnemonics
+  inline void xxspltd(  VectorSRegister d, VectorSRegister a, int x);
+  inline void xxmrghd(  VectorSRegister d, VectorSRegister a, VectorSRegister b);
+  inline void xxmrgld(  VectorSRegister d, VectorSRegister a, VectorSRegister b);
+  inline void xxswapd(  VectorSRegister d, VectorSRegister a);
 
   // Vector-Scalar (VSX) instructions.
   inline void mtfprd(   FloatRegister   d, Register a);
--- a/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/ppc/vm/assembler_ppc.inline.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -758,12 +758,23 @@
 inline void Assembler::lvsr(  VectorRegister d, Register s1, Register s2) { emit_int32( LVSR_OPCODE   | vrt(d) | ra0mem(s1) | rb(s2)); }
 
 // Vector-Scalar (VSX) instructions.
-inline void Assembler::lxvd2x (VectorSRegister d, Register s1) { emit_int32( LXVD2X_OPCODE  | vsrt(d) | ra(0) | rb(s1)); }
-inline void Assembler::lxvd2x (VectorSRegister d, Register s1, Register s2) { emit_int32( LXVD2X_OPCODE  | vsrt(d) | ra0mem(s1) | rb(s2)); }
-inline void Assembler::stxvd2x(VectorSRegister d, Register s1) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra(0) | rb(s1)); }
-inline void Assembler::stxvd2x(VectorSRegister d, Register s1, Register s2) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); }
-inline void Assembler::mtvrd(  VectorRegister  d, Register a)               { emit_int32( MTVSRD_OPCODE  | vrt(d)  | ra(a)  | 1u); } // 1u: d is treated as Vector (VMX/Altivec).
-inline void Assembler::mfvrd(  Register        a, VectorRegister d)         { emit_int32( MFVSRD_OPCODE  | vrt(d)  | ra(a)  | 1u); } // 1u: d is treated as Vector (VMX/Altivec).
+inline void Assembler::lxvd2x(  VectorSRegister d, Register s1)              { emit_int32( LXVD2X_OPCODE  | vsrt(d) | ra(0) | rb(s1)); }
+inline void Assembler::lxvd2x(  VectorSRegister d, Register s1, Register s2) { emit_int32( LXVD2X_OPCODE  | vsrt(d) | ra0mem(s1) | rb(s2)); }
+inline void Assembler::stxvd2x( VectorSRegister d, Register s1)              { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra(0) | rb(s1)); }
+inline void Assembler::stxvd2x( VectorSRegister d, Register s1, Register s2) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); }
+inline void Assembler::mtvrd(   VectorRegister  d, Register a)               { emit_int32( MTVSRD_OPCODE  | vsrt(d->to_vsr()) | ra(a)); }
+inline void Assembler::mfvrd(   Register        a, VectorRegister d)         { emit_int32( MFVSRD_OPCODE  | vsrt(d->to_vsr()) | ra(a)); }
+inline void Assembler::mtvrwz(  VectorRegister  d, Register a)               { emit_int32( MTVSRWZ_OPCODE | vsrt(d->to_vsr()) | ra(a)); }
+inline void Assembler::mfvrwz(  Register        a, VectorRegister d)         { emit_int32( MFVSRWZ_OPCODE | vsrt(d->to_vsr()) | ra(a)); }
+inline void Assembler::xxpermdi(VectorSRegister d, VectorSRegister a, VectorSRegister b, int dm) { emit_int32( XXPERMDI_OPCODE | vsrt(d) | vsra(a) | vsrb(b) | vsdm(dm)); }
+inline void Assembler::xxmrghw( VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XXMRGHW_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
+inline void Assembler::xxmrglw( VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XXMRGHW_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
+
+// VSX Extended Mnemonics
+inline void Assembler::xxspltd( VectorSRegister d, VectorSRegister a, int x)             { xxpermdi(d, a, a, x ? 3 : 0); }
+inline void Assembler::xxmrghd( VectorSRegister d, VectorSRegister a, VectorSRegister b) { xxpermdi(d, a, b, 0); }
+inline void Assembler::xxmrgld( VectorSRegister d, VectorSRegister a, VectorSRegister b) { xxpermdi(d, a, b, 3); }
+inline void Assembler::xxswapd( VectorSRegister d, VectorSRegister a)                    { xxpermdi(d, a, a, 2); }
 
 // Vector-Scalar (VSX) instructions.
 inline void Assembler::mtfprd(  FloatRegister   d, Register a)      { emit_int32( MTVSRD_OPCODE  | frt(d)  | ra(a)); }
@@ -800,7 +811,7 @@
 inline void Assembler::vperm(   VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VPERM_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); }
 inline void Assembler::vsel(    VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VSEL_OPCODE  | vrt(d) | vra(a) | vrb(b) | vrc(c)); }
 inline void Assembler::vsl(     VectorRegister d, VectorRegister a, VectorRegister b)                  { emit_int32( VSL_OPCODE   | vrt(d) | vra(a) | vrb(b)); }
-inline void Assembler::vsldoi(  VectorRegister d, VectorRegister a, VectorRegister b, int si4)         { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(simm(si4,4))); }
+inline void Assembler::vsldoi(  VectorRegister d, VectorRegister a, VectorRegister b, int ui4)         { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(uimm(ui4,4))); }
 inline void Assembler::vslo(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSLO_OPCODE    | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vsr(     VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSR_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vsro(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRO_OPCODE    | vrt(d) | vra(a) | vrb(b)); }
@@ -811,6 +822,7 @@
 inline void Assembler::vaddubm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUBM_OPCODE | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vadduwm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUWM_OPCODE | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vadduhm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUHM_OPCODE | vrt(d) | vra(a) | vrb(b)); }
+inline void Assembler::vaddudm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUDM_OPCODE | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vaddubs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUBS_OPCODE | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vadduws( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUWS_OPCODE | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vadduhs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUHS_OPCODE | vrt(d) | vra(a) | vrb(b)); }
@@ -887,6 +899,7 @@
 inline void Assembler::vandc(   VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VANDC_OPCODE    | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vnor(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNOR_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vor(     VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VOR_OPCODE      | vrt(d) | vra(a) | vrb(b)); }
+inline void Assembler::vmr(     VectorRegister d, VectorRegister a)                   { emit_int32( VOR_OPCODE      | vrt(d) | vra(a) | vrb(a)); }
 inline void Assembler::vxor(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VXOR_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vrld(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLD_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
 inline void Assembler::vrlb(    VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLB_OPCODE     | vrt(d) | vra(a) | vrb(b)); }
--- a/src/cpu/ppc/vm/c2_globals_ppc.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/ppc/vm/c2_globals_ppc.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -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/macroAssembler_ppc.cpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -4576,12 +4576,12 @@
   vspltisw(VR0, -1);
 
   vsldoi(mask_32bit, zeroes, VR0, 4);
-  vsldoi(mask_64bit, zeroes, VR0, -8);
+  vsldoi(mask_64bit, zeroes, VR0, 8);
 
   // Get the initial value into v8
   vxor(VR8, VR8, VR8);
   mtvrd(VR8, crc);
-  vsldoi(VR8, zeroes, VR8, -8); // shift into bottom 32 bits
+  vsldoi(VR8, zeroes, VR8, 8); // shift into bottom 32 bits
 
   li (rLoaded, 0);
 
@@ -4930,7 +4930,7 @@
   addi(barretConstants, barretConstants, 16);
   lvx(const2, barretConstants);
 
-  vsldoi(VR1, VR0, VR0, -8);
+  vsldoi(VR1, VR0, VR0, 8);
   vxor(VR0, VR0, VR1);    // xor two 64 bit results together
 
   // shift left one bit
--- a/src/cpu/ppc/vm/ppc.ad	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/ppc/vm/ppc.ad	Thu Aug 24 09:44:52 2017 +0200
@@ -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/ppc/vm/register_ppc.cpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/ppc/vm/register_ppc.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2013 SAP SE. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -81,8 +81,17 @@
     "VSR0",  "VSR1",  "VSR2",  "VSR3",  "VSR4",  "VSR5",  "VSR6",  "VSR7",
     "VSR8",  "VSR9",  "VSR10", "VSR11", "VSR12", "VSR13", "VSR14", "VSR15",
     "VSR16", "VSR17", "VSR18", "VSR19", "VSR20", "VSR21", "VSR22", "VSR23",
-    "VSR24", "VSR25", "VSR26", "VSR27", "VSR28", "VSR29", "VSR30", "VSR31"
+    "VSR24", "VSR25", "VSR26", "VSR27", "VSR28", "VSR29", "VSR30", "VSR31",
+    "VSR32", "VSR33", "VSR34", "VSR35", "VSR36", "VSR37", "VSR38", "VSR39",
+    "VSR40", "VSR41", "VSR42", "VSR43", "VSR44", "VSR45", "VSR46", "VSR47",
+    "VSR48", "VSR49", "VSR50", "VSR51", "VSR52", "VSR53", "VSR54", "VSR55",
+    "VSR56", "VSR57", "VSR58", "VSR59", "VSR60", "VSR61", "VSR62", "VSR63"
   };
   return is_valid() ? names[encoding()] : "vsnoreg";
 }
 
+// Method to convert a VectorRegister to a Vector-Scalar Register (VectorSRegister)
+VectorSRegister VectorRegisterImpl::to_vsr() const {
+  if (this == vnoreg) { return vsnoregi; }
+  return as_VectorSRegister(encoding() + 32);
+}
--- a/src/cpu/ppc/vm/register_ppc.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/ppc/vm/register_ppc.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -398,6 +398,11 @@
   return (VectorRegister)(intptr_t)encoding;
 }
 
+// Forward declaration
+// Use VectorSRegister as a shortcut.
+class VectorSRegisterImpl;
+typedef VectorSRegisterImpl* VectorSRegister;
+
 // The implementation of vector registers for the Power architecture
 class VectorRegisterImpl: public AbstractRegisterImpl {
  public:
@@ -415,6 +420,9 @@
   bool is_valid()       const { return   0 <=  value()       &&  value() < number_of_registers; }
 
   const char* name() const;
+
+  // convert to VSR
+  VectorSRegister to_vsr() const;
 };
 
 // The Vector registers of the Power architecture
@@ -491,10 +499,6 @@
 #endif // DONT_USE_REGISTER_DEFINES
 
 
-// Use VectorSRegister as a shortcut.
-class VectorSRegisterImpl;
-typedef VectorSRegisterImpl* VectorSRegister;
-
 inline VectorSRegister as_VectorSRegister(int encoding) {
   return (VectorSRegister)(intptr_t)encoding;
 }
@@ -503,7 +507,7 @@
 class VectorSRegisterImpl: public AbstractRegisterImpl {
  public:
   enum {
-    number_of_registers = 32
+    number_of_registers = 64
   };
 
   // construction
@@ -554,6 +558,38 @@
 CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR29, (29));
 CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR30, (30));
 CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR31, (31));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR32, (32));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR33, (33));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR34, (34));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR35, (35));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR36, (36));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR37, (37));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR38, (38));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR39, (39));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR40, (40));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR41, (41));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR42, (42));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR43, (43));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR44, (44));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR45, (45));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR46, (46));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR47, (47));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR48, (48));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR49, (49));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR50, (50));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR51, (51));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR52, (52));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR53, (53));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR54, (54));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR55, (55));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR56, (56));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR57, (57));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR58, (58));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR59, (59));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR60, (60));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR61, (61));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR62, (62));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR63, (63));
 
 #ifndef DONT_USE_REGISTER_DEFINES
 #define vsnoregi ((VectorSRegister)(vsnoreg_VectorSRegisterEnumValue))
@@ -589,6 +625,38 @@
 #define VSR29   ((VectorSRegister)(  VSR29_VectorSRegisterEnumValue))
 #define VSR30   ((VectorSRegister)(  VSR30_VectorSRegisterEnumValue))
 #define VSR31   ((VectorSRegister)(  VSR31_VectorSRegisterEnumValue))
+#define VSR32   ((VectorSRegister)(  VSR32_VectorSRegisterEnumValue))
+#define VSR33   ((VectorSRegister)(  VSR33_VectorSRegisterEnumValue))
+#define VSR34   ((VectorSRegister)(  VSR34_VectorSRegisterEnumValue))
+#define VSR35   ((VectorSRegister)(  VSR35_VectorSRegisterEnumValue))
+#define VSR36   ((VectorSRegister)(  VSR36_VectorSRegisterEnumValue))
+#define VSR37   ((VectorSRegister)(  VSR37_VectorSRegisterEnumValue))
+#define VSR38   ((VectorSRegister)(  VSR38_VectorSRegisterEnumValue))
+#define VSR39   ((VectorSRegister)(  VSR39_VectorSRegisterEnumValue))
+#define VSR40   ((VectorSRegister)(  VSR40_VectorSRegisterEnumValue))
+#define VSR41   ((VectorSRegister)(  VSR41_VectorSRegisterEnumValue))
+#define VSR42   ((VectorSRegister)(  VSR42_VectorSRegisterEnumValue))
+#define VSR43   ((VectorSRegister)(  VSR43_VectorSRegisterEnumValue))
+#define VSR44   ((VectorSRegister)(  VSR44_VectorSRegisterEnumValue))
+#define VSR45   ((VectorSRegister)(  VSR45_VectorSRegisterEnumValue))
+#define VSR46   ((VectorSRegister)(  VSR46_VectorSRegisterEnumValue))
+#define VSR47   ((VectorSRegister)(  VSR47_VectorSRegisterEnumValue))
+#define VSR48   ((VectorSRegister)(  VSR48_VectorSRegisterEnumValue))
+#define VSR49   ((VectorSRegister)(  VSR49_VectorSRegisterEnumValue))
+#define VSR50   ((VectorSRegister)(  VSR50_VectorSRegisterEnumValue))
+#define VSR51   ((VectorSRegister)(  VSR51_VectorSRegisterEnumValue))
+#define VSR52   ((VectorSRegister)(  VSR52_VectorSRegisterEnumValue))
+#define VSR53   ((VectorSRegister)(  VSR53_VectorSRegisterEnumValue))
+#define VSR54   ((VectorSRegister)(  VSR54_VectorSRegisterEnumValue))
+#define VSR55   ((VectorSRegister)(  VSR55_VectorSRegisterEnumValue))
+#define VSR56   ((VectorSRegister)(  VSR56_VectorSRegisterEnumValue))
+#define VSR57   ((VectorSRegister)(  VSR57_VectorSRegisterEnumValue))
+#define VSR58   ((VectorSRegister)(  VSR58_VectorSRegisterEnumValue))
+#define VSR59   ((VectorSRegister)(  VSR59_VectorSRegisterEnumValue))
+#define VSR60   ((VectorSRegister)(  VSR60_VectorSRegisterEnumValue))
+#define VSR61   ((VectorSRegister)(  VSR61_VectorSRegisterEnumValue))
+#define VSR62   ((VectorSRegister)(  VSR62_VectorSRegisterEnumValue))
+#define VSR63   ((VectorSRegister)(  VSR63_VectorSRegisterEnumValue))
 #endif // DONT_USE_REGISTER_DEFINES
 
 // Maximum number of incoming arguments that can be passed in i registers.
@@ -609,7 +677,7 @@
       * 2                                          // register halves
       + ConditionRegisterImpl::number_of_registers // condition code registers
       + SpecialRegisterImpl::number_of_registers   // special registers
-      + VectorRegisterImpl::number_of_registers    // vector registers
+      + VectorRegisterImpl::number_of_registers    // VSX registers
   };
 
   static const int max_gpr;
--- a/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/ppc/vm/stubGenerator_ppc.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -2729,7 +2729,7 @@
     __ vspltisb        (vTmp2, -16);
     __ vrld            (keyPerm, keyPerm, vTmp2);
     __ vrld            (keyPerm, keyPerm, vTmp2);
-    __ vsldoi          (keyPerm, keyPerm, keyPerm, -8);
+    __ vsldoi          (keyPerm, keyPerm, keyPerm, 8);
 
     // load the 1st round key to vKey1
     __ li              (keypos, 0);
@@ -2929,7 +2929,7 @@
     __ vspltisb        (vTmp2, -16);
     __ vrld            (keyPerm, keyPerm, vTmp2);
     __ vrld            (keyPerm, keyPerm, vTmp2);
-    __ vsldoi          (keyPerm, keyPerm, keyPerm, -8);
+    __ vsldoi          (keyPerm, keyPerm, keyPerm, 8);
 
     __ cmpwi           (CCR0, keylen, 44);
     __ beq             (CCR0, L_do44);
--- a/src/cpu/s390/vm/c2_globals_s390.hpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/s390/vm/c2_globals_s390.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/s390/vm/s390.ad	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/s390/vm/stubGenerator_s390.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/s390/vm/vm_version_s390.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/sparc/vm/sparc.ad	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/x86/vm/c2_globals_x86.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/x86/vm/globals_x86.hpp	Thu Aug 24 09:44:52 2017 +0200
@@ -119,7 +119,7 @@
   product(bool, UseStoreImmI16, true,                                       \
           "Use store immediate 16-bits value instruction on x86")           \
                                                                             \
-  product(intx, UseAVX, 99,                                                 \
+  product(intx, UseAVX, 3,                                                  \
           "Highest supported AVX instructions set on x86/x64")              \
           range(0, 99)                                                      \
                                                                             \
--- a/src/cpu/x86/vm/interp_masm_x86.cpp	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/x86/vm/interp_masm_x86.cpp	Thu Aug 24 09:44:52 2017 +0200
@@ -1121,7 +1121,6 @@
 
     call_VM_leaf(
       CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), rthread);
-    push(rthread);
     call_VM(noreg, CAST_FROM_FN_PTR(address,
                    InterpreterRuntime::throw_delayed_StackOverflowError));
     should_not_reach_here();
--- a/src/cpu/x86/vm/x86_32.ad	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/x86/vm/x86_32.ad	Thu Aug 24 09:44:52 2017 +0200
@@ -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	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/cpu/x86/vm/x86_64.ad	Thu Aug 24 09:44:52 2017 +0200
@@ -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.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java	Thu Aug 24 09:44:52 2017 +0200
@@ -53,9 +53,8 @@
     private static int shStrTabNrOfBytes = 0;
 
     public ElfSection(String sectName, byte [] sectData, int sectFlags,
-                      int sectType, boolean hasRelocations, int sectIndex) {
-
-        long align;
+                      int sectType, boolean hasRelocations, int align,
+                      int sectIndex) {
 
         section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize);
 
@@ -90,35 +89,19 @@
 
         section.putLong(Elf64_Shdr.sh_entsize.off, 0);
 
-        // Determine the alignment and entrysize
+        // Determine the entrysize
         // based on type of section
         switch (sectType) {
-            case Elf64_Shdr.SHT_PROGBITS:
-                if ((sectFlags & Elf64_Shdr.SHF_EXECINSTR) != 0)
-                    align = 16;
-                else
-                    align = 4;
-                break;
             case Elf64_Shdr.SHT_SYMTAB:
-                align = 8;
                 section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Sym.totalsize);
                 break;
-            case Elf64_Shdr.SHT_STRTAB:
-                align = 1;
-                break;
             case Elf64_Shdr.SHT_RELA:
-                align = 8;
                 section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rela.totalsize);
                 break;
             case Elf64_Shdr.SHT_REL:
-                align = 8;
                 section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rel.totalsize);
                 break;
-            case Elf64_Shdr.SHT_NOBITS:
-                align = 4;
-                break;
             default:
-                align = 8;
                 break;
         }
         section.putLong(Elf64_Shdr.sh_addralign.off, align);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java	Thu Aug 24 09:44:52 2017 +0200
@@ -69,6 +69,7 @@
                                          String sectName,
                                          byte [] scnData,
                                          boolean hasRelocs,
+                                         int align,
                                          int scnFlags,
                                          int scnType) {
 
@@ -77,6 +78,7 @@
                                          scnFlags,
                                          scnType,
                                          hasRelocs,
+                                         align,
                                          sections.size());
         // Add this section to our list
         sections.add(sect);
@@ -91,7 +93,7 @@
         byte[] scnData = c.getByteArray();
 
         int scnType = Elf64_Shdr.SHT_PROGBITS;
-        boolean zeros = hasRelocs;
+        boolean zeros = !hasRelocs;
         if (zeros) {
             for (byte b : scnData) {
                 if (b != 0) {
@@ -105,7 +107,7 @@
         }
 
         sect = createByteSection(sections, c.getContainerName(),
-                                 scnData, hasRelocs,
+                                 scnData, hasRelocs, segmentSize,
                                  scnFlags, scnType);
         c.setSectionId(sect.getSectionId());
     }
@@ -136,7 +138,7 @@
         ArrayList<ElfSection> sections = new ArrayList<ElfSection>();
 
         // Create the null section
-        createByteSection(sections, null, null, false, 0, 0);
+        createByteSection(sections, null, null, false, 1, 0, 0);
 
         // Create text section
         createCodeSection(sections, binContainer.getCodeContainer());
@@ -170,6 +172,7 @@
                                                      ".strtab",
                                                      symtab.getStrtabArray(),
                                                      false,
+                                                     1,
                                                      0,
                                                      Elf64_Shdr.SHT_STRTAB);
 
@@ -181,6 +184,7 @@
                                                     ".symtab",
                                                     symtab.getSymtabArray(),
                                                     false,
+                                                    8,
                                                     0,
                                                     Elf64_Shdr.SHT_SYMTAB);
         symTabSection.setLink(strTabSection.getSectionId());
@@ -196,6 +200,7 @@
                                                     ".shstrtab",
                                                     null,
                                                     false,
+                                                    1,
                                                     0,
                                                     Elf64_Shdr.SHT_STRTAB);
         eh.setSectionStrNdx(shStrTabSection.getSectionId());
@@ -435,13 +440,14 @@
                 ElfSection sect = sections.get(i);
                 String relname = ".rela" + sect.getName();
                 ElfSection relocSection = createByteSection(sections,
-                                                            relname,
-                                                            elfRelocTable.getRelocData(i),
-                                                            false,
-                                                            0,
-                                                            Elf64_Shdr.SHT_RELA);
-                relocSection.setLink(symtabsectidx);
-                relocSection.setInfo(sect.getSectionId());
+                                                                    relname,
+                                                                    elfRelocTable.getRelocData(i),
+                                                                    false,
+                                                                    8,
+                                                                    0,
+                                                                    Elf64_Shdr.SHT_RELA);
+                        relocSection.setLink(symtabsectidx);
+                        relocSection.setInfo(sect.getSectionId());
             }
         }
     }
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java	Thu Aug 24 09:44:52 2017 +0200
@@ -96,7 +96,8 @@
                                              segName,
                                              c.getByteArray(),
                                              scnFlags,
-                                             c.hasRelocations());
+                                             c.hasRelocations(),
+                                             segmentSize);
         // Add this section to our list
         sections.add(sect);
 
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java	Thu Aug 24 09:44:52 2017 +0200
@@ -35,7 +35,7 @@
     byte [] data;
     boolean hasrelocations;
 
-    public MachOSection(String sectName, String segName, byte [] sectData, int sectFlags, boolean hasRelocations) {
+    public MachOSection(String sectName, String segName, byte [] sectData, int sectFlags, boolean hasRelocations, int align) {
         section = MachOByteBuffer.allocate(section_64.totalsize);
 
         // TODO: Hotspot uses long section names.
@@ -57,8 +57,8 @@
 
         section.putLong(section_64.size.off, sectData.length);
 
-        // For now use 8 byte alignment
-        section.putInt(section_64.align.off, 3);
+        section.putInt(section_64.align.off,
+                       31 - Integer.numberOfLeadingZeros(align));
 
         section.putInt(section_64.flags.off, sectFlags);
 
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java	Thu Aug 24 09:44:52 2017 +0200
@@ -62,6 +62,9 @@
         this.binContainer = binContainer;
         this.pecoffContainer = new PECoffContainer(outputFileName, aotVersion);
         this.segmentSize = binContainer.getCodeSegmentSize();
+        if (segmentSize != 64) {
+            System.out.println("binContainer alignment size not 64 bytes, update JPECoffRelocObject");
+        }
     }
 
     private PECoffSection createByteSection(ArrayList<PECoffSection>sections,
@@ -97,20 +100,20 @@
     private void createCodeSection(ArrayList<PECoffSection>sections, CodeContainer c) {
         createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
                                        IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE |
-                                       IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_16BYTES |
+                                       IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES |
                                        IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE);
     }
 
     private void createReadOnlySection(ArrayList<PECoffSection>sections, ReadOnlyDataContainer c) {
         createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
-                                       IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_16BYTES |
+                                       IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES |
                                        IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA);
     }
 
     private void createReadWriteSection(ArrayList<PECoffSection>sections, ByteContainer c) {
         int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
                        IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE |
-                       IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_8BYTES;
+                       IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES;
 
         if (c.getByteArray().length > 0)
             scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java	Thu Aug 24 09:44:52 2017 +0200
@@ -111,6 +111,8 @@
         public static final int IMAGE_SCN_ALIGN_4BYTES           = 0x300000;
         public static final int IMAGE_SCN_ALIGN_8BYTES           = 0x400000;
         public static final int IMAGE_SCN_ALIGN_16BYTES          = 0x500000;
+        public static final int IMAGE_SCN_ALIGN_32BYTES          = 0x600000;
+        public static final int IMAGE_SCN_ALIGN_64BYTES          = 0x700000;
         public static final int IMAGE_SCN_ALIGN_MASK             = 0xf00000;
         public static final int IMAGE_SCN_ALIGN_SHIFT            = 20;
 
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Thu Aug 24 09:44:52 2017 +0200
@@ -247,7 +247,7 @@
 
     public static class Options {
         public List<SearchFor> files = new LinkedList<>();
-        public String outputName = "unnamed.so";
+        public String outputName = defaultOutputName();
         public String methodList;
         public List<ClassSource> sources = new ArrayList<>();
         public String linkerpath = null;
@@ -269,6 +269,30 @@
         public boolean version;
         public boolean compileWithAssertions;
         public boolean tiered;
+
+        private static String defaultOutputName() {
+            String osName = System.getProperty("os.name");
+            String name = "unnamed.";
+            String ext;
+
+            switch (osName) {
+                case "Linux":
+                case "SunOS":
+                    ext = "so";
+                    break;
+                case "Mac OS X":
+                    ext = "dylib";
+                    break;
+                default:
+                    if (osName.startsWith("Windows")) {
+                        ext = "dll";
+                    } else {
+                        ext = "so";
+                    }
+            }
+
+            return name + ext;
+        }
     }
 
     /* package */final Options options = new Options();
@@ -529,45 +553,41 @@
             String name = options.outputName;
             String objectFileName = name;
 
-            // [TODO] The jtregs tests expect .so extension so don't
-            // override with platform specific file extension until the
-            // tests are fixed.
             String libraryFileName = name;
 
             String linkerCmd;
             String linkerPath;
             String osName = System.getProperty("os.name");
 
-            if (name.endsWith(".so")) {
-                objectFileName = name.substring(0, name.length() - ".so".length());
-            } else if (name.endsWith(".dylib")) {
-                objectFileName = name.substring(0, name.length() - ".dylib".length());
-            } else if (name.endsWith(".dll")) {
-                objectFileName = name.substring(0, name.length() - ".dll".length());
-            }
-
             switch (osName) {
                 case "Linux":
-                    // libraryFileName = options.outputName + ".so";
-                    objectFileName = objectFileName + ".o";
+                    if (name.endsWith(".so")) {
+                        objectFileName = name.substring(0, name.length() - ".so".length());
+                    }
                     linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
                     linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName;
                     break;
                 case "SunOS":
-                    // libraryFileName = options.outputName + ".so";
+                    if (name.endsWith(".so")) {
+                        objectFileName = name.substring(0, name.length() - ".so".length());
+                    }
                     objectFileName = objectFileName + ".o";
                     linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
                     linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName;
                     break;
                 case "Mac OS X":
-                    // libraryFileName = options.outputName + ".dylib";
+                    if (name.endsWith(".dylib")) {
+                        objectFileName = name.substring(0, name.length() - ".dylib".length());
+                    }
                     objectFileName = objectFileName + ".o";
                     linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
                     linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName;
                     break;
                 default:
                     if (osName.startsWith("Windows")) {
-                        // libraryFileName = options.outputName + ".dll";
+                        if (name.endsWith(".dll")) {
+                            objectFileName = name.substring(0, name.length() - ".dll".length());
+                        }
                         objectFileName = objectFileName + ".obj";
                         linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath();
                         if (linkerPath == null) {
@@ -575,8 +595,9 @@
                         }
                         linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName;
                         break;
-                    } else
+                    } else {
                         throw new InternalError("Unsupported platform: " + osName);
+                    }
             }
 
             try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) {
--- a/src/jdk.hotspot.agent/doc/jsdb.html	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/doc/jsdb.html	Thu Aug 24 09:44:52 2017 +0200
@@ -1108,11 +1108,6 @@
 calls callback with Klass and initiating loader (Oop) for System dictionary
 entry.
 </dd>
-<dt>forEachPrimArrayKlass(callback)</dt>
-<dd>
-calls callback with Klass and initiating loader (Oop) for each
-primitive array Klass in the system.
-</dd>
 <dt>findInstanceKlass(name)</dt>
 <dd>
 finds the first instance klass with given name from System dictionary
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -48,6 +48,7 @@
 import sun.jvm.hotspot.code.NMethod;
 import sun.jvm.hotspot.debugger.Address;
 import sun.jvm.hotspot.debugger.OopHandle;
+import sun.jvm.hotspot.classfile.ClassLoaderDataGraph;
 import sun.jvm.hotspot.memory.SymbolTable;
 import sun.jvm.hotspot.memory.SystemDictionary;
 import sun.jvm.hotspot.memory.Universe;
@@ -853,8 +854,8 @@
                 } else {
                     String s = t.nextToken();
                     if (s.equals("-a")) {
-                        SystemDictionary sysDict = VM.getVM().getSystemDictionary();
-                        sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
+                        ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+                        cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
                                 public void visit(Klass k) {
                                     if (k instanceof InstanceKlass) {
                                         MethodArray methods = ((InstanceKlass)k).getMethods();
@@ -887,8 +888,8 @@
                 if (t.countTokens() != 0) {
                     usage();
                 } else {
-                    SystemDictionary sysDict = VM.getVM().getSystemDictionary();
-                    sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
+                    ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+                    cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
                             public void visit(Klass k) {
                                 if (k instanceof InstanceKlass && ((InstanceKlass)k).getConstants().getCache() != null) {
                                     MethodArray methods = ((InstanceKlass)k).getMethods();
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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,16 +25,16 @@
 package sun.jvm.hotspot.classfile;
 
 import java.io.PrintStream;
-import java.util.*;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.types.*;
 
 public class ClassLoaderData extends VMObject {
   static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
+    VM.registerVMInitializedObserver(new java.util.Observer() {
+        public void update(java.util.Observable o, Object data) {
           initialize(VM.getVM().getTypeDataBase());
         }
       });
@@ -44,19 +44,26 @@
     Type type      = db.lookupType("ClassLoaderData");
     classLoaderField = type.getOopField("_class_loader");
     nextField = type.getAddressField("_next");
-    klassesField = type.getAddressField("_klasses");
+    klassesField = new MetadataField(type.getAddressField("_klasses"), 0);
     isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0);
+    dictionaryField = type.getAddressField("_dictionary");
   }
 
   private static sun.jvm.hotspot.types.OopField classLoaderField;
   private static AddressField nextField;
-  private static AddressField klassesField;
+  private static MetadataField  klassesField;
   private static CIntField isAnonymousField;
+  private static AddressField dictionaryField;
 
   public ClassLoaderData(Address addr) {
     super(addr);
   }
 
+  public Dictionary dictionary() {
+      Address tmp = dictionaryField.getValue();
+      return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
+  }
+
   public static ClassLoaderData instantiateWrapperFor(Address addr) {
     if (addr == null) {
       return null;
@@ -76,7 +83,30 @@
     return instantiateWrapperFor(nextField.getValue(getAddress()));
   }
 
-  public Klass getKlasses() {
-    return (InstanceKlass)Metadata.instantiateWrapperFor(klassesField.getValue(getAddress()));
+  public Klass getKlasses()    { return (Klass)klassesField.getValue(this);  }
+
+  /** Lookup an already loaded class. If not found null is returned. */
+  public Klass find(Symbol className) {
+    for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
+        if (className.equals(l.getName())) {
+            return l;
+        }
+    }
+    return null;
+  }
+
+  /** Iterate over all klasses - including object, primitive
+      array klasses */
+  public void classesDo(ClassLoaderDataGraph.ClassVisitor v) {
+      for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
+          v.visit(l);
+      }
+  }
+
+  /** Iterate over all klasses in the dictionary, including initiating loader. */
+  public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v) {
+      for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) {
+          dictionary().allEntriesDo(v, getClassLoader());
+      }
   }
 }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -27,6 +27,7 @@
 import java.io.PrintStream;
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.types.*;
@@ -52,21 +53,43 @@
     return ClassLoaderData.instantiateWrapperFor(headField.getValue());
   }
 
-  public static interface KlassVisitor {
+  /** Lookup an already loaded class in any class loader. */
+  public Klass find(String className) {
+    Symbol sym = VM.getVM().getSymbolTable().probe(className);
+    if (sym == null) return null;
+    for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
+        Klass k = cld.find(sym);
+        if (k != null) {
+            return k;
+        }
+    }
+    return null;
+  }
+
+  /** Interface for iterating through all classes. */
+  public static interface ClassVisitor {
     public void visit(Klass k);
   }
 
-  /** Iterate over all anonymous class loaders and the klasses in those */
-  public void allAnonymousKlassesDo(final KlassVisitor v) {
-    for (ClassLoaderData cl = getClassLoaderGraphHead();
-         cl != null;
-         cl = cl.next()) {
-      if (cl.getIsAnonymous() == true) {
-        for (Klass k = cl.getKlasses(); k != null; k = k.getNextLinkKlass()) {
-          v.visit(k);
-        }
-      }
+  /** Interface for iterating through all classes and their class
+      loaders in dictionary */
+  public static interface ClassAndLoaderVisitor {
+    public void visit(Klass k, Oop loader);
+  }
+
+  /** Iterate over all klasses - including object, primitive
+      array klasses */
+  public void classesDo(ClassVisitor v) {
+    for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
+        cld.classesDo(v);
     }
   }
 
+  /** Iterate over all klasses - including object, primitive
+      array klasses, pass initiating loader. */
+  public void allEntriesDo(ClassAndLoaderVisitor v) {
+    for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) {
+        cld.allEntriesDo(v);
+    }
+  }
 }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, 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
@@ -26,12 +26,13 @@
 
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.types.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.utilities.*;
 
-public class Dictionary extends TwoOopHashtable {
+public class Dictionary extends sun.jvm.hotspot.utilities.Hashtable {
   static {
     VM.registerVMInitializedObserver(new Observer() {
         public void update(Observable o, Object data) {
@@ -55,56 +56,32 @@
     return DictionaryEntry.class;
   }
 
-  /** Iterate over all klasses in dictionary; just the classes from
-      declaring class loaders */
-  public void classesDo(SystemDictionary.ClassVisitor v) {
-    ObjectHeap heap = VM.getVM().getObjectHeap();
+  /** All classes, and their initiating class loader, passed in. */
+  public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v, Oop loader) {
     int tblSize = tableSize();
     for (int index = 0; index < tblSize; index++) {
       for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null;
-                                             probe = (DictionaryEntry) probe.next()) {
+                                              probe = (DictionaryEntry) probe.next()) {
         Klass k = probe.klass();
-        if (heap.equal(probe.loader(), ((InstanceKlass) k).getClassLoader())) {
-            v.visit(k);
-        }
+        v.visit(k, loader);
       }
     }
   }
 
-  /** All classes, and their class loaders */
-  public void classesDo(SystemDictionary.ClassAndLoaderVisitor v) {
-    int tblSize = tableSize();
-    for (int index = 0; index < tblSize; index++) {
-      for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null;
-                                             probe = (DictionaryEntry) probe.next()) {
-        Klass k = probe.klass();
-        v.visit(k, probe.loader());
-      }
-    }
-  }
-
-  public Klass find(int index, long hash, Symbol className, Oop classLoader, Oop protectionDomain) {
-    DictionaryEntry entry = getEntry(index, hash, className, classLoader);
-    if (entry != null && entry.isValidProtectionDomain(protectionDomain)) {
-      return entry.klass();
-    }
-    return null;
-  }
-
   // - Internals only below this point
 
-  private DictionaryEntry getEntry(int index, long hash, Symbol className, Oop classLoader) {
+  private DictionaryEntry getEntry(int index, long hash, Symbol className) {
     for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null;
                                     entry = (DictionaryEntry) entry.next()) {
-      if (entry.hash() == hash && entry.equals(className, classLoader)) {
+      if (entry.hash() == hash && entry.equals(className)) {
         return entry;
       }
     }
     return null;
   }
 
-  public boolean contains(Klass c, Oop classLoader) {
-    long hash = computeHash(c.getName(), classLoader);
+  public boolean contains(Klass c) {
+    long hash = computeHash(c.getName());
     int index = hashToIndex(hash);
 
     for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, 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
@@ -43,28 +43,6 @@
 
   private static synchronized void initialize(TypeDataBase db) {
     Type type = db.lookupType("DictionaryEntry");
-    pdSetField = type.getAddressField("_pd_set");
-    loaderDataField = type.getAddressField("_loader_data");
-  }
-
-  // Fields
-  private static AddressField pdSetField;
-  private static AddressField loaderDataField;
-
-  // Accessors
-
-  public ProtectionDomainEntry pdSet() {
-    Address tmp = pdSetField.getValue(addr);
-    return (ProtectionDomainEntry) VMObjectFactory.newObject(
-                          ProtectionDomainEntry.class, tmp);
-  }
-
-  public Oop loader() {
-    return loaderData().getClassLoader();
-  }
-
-  public ClassLoaderData loaderData() {
-    return ClassLoaderData.instantiateWrapperFor(loaderDataField.getValue(addr));
   }
 
   public Klass klass() {
@@ -75,38 +53,9 @@
     super(addr);
   }
 
-  public boolean equals(Symbol className, Oop classLoader) {
+  public boolean equals(Symbol className) {
     InstanceKlass ik = (InstanceKlass) klass();
-    Oop loader = loader();
-    if (! ik.getName().equals(className)) {
-      return false;
-    } else {
-      return (loader == null)? (classLoader == null) :
-                               (loader.equals(classLoader));
-    }
-  }
-
-  public boolean isValidProtectionDomain(Oop protectionDomain) {
-    if (protectionDomain == null) {
-      return true;
-    } else {
-      return containsProtectionDomain(protectionDomain);
-    }
-  }
-
-  public boolean containsProtectionDomain(Oop protectionDomain) {
-    InstanceKlass ik = (InstanceKlass) klass();
-    // Currently unimplemented and not used.
-    // if (protectionDomain.equals(ik.getJavaMirror().getProtectionDomain())) {
-    //   return true; // Succeeds trivially
-    // }
-    for (ProtectionDomainEntry current = pdSet(); current != null;
-                                       current = current.next()) {
-      if (protectionDomain.equals(current.protectionDomain())) {
-        return true;
-      }
-    }
-    return false;
+    return ik.getName().equals(className);
   }
 
   /* covariant return type :-(
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java	Mon Aug 21 14:05:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class LoaderConstraintEntry extends sun.jvm.hotspot.utilities.HashtableEntry {
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static synchronized void initialize(TypeDataBase db) {
-    Type type = db.lookupType("LoaderConstraintEntry");
-    nameField = type.getAddressField("_name");
-    numLoadersField = type.getCIntegerField("_num_loaders");
-    maxLoadersField = type.getCIntegerField("_max_loaders");
-    loadersField = type.getAddressField("_loaders");
-  }
-
-  // Fields
-  private static AddressField nameField;
-  private static CIntegerField numLoadersField;
-  private static CIntegerField maxLoadersField;
-  private static AddressField loadersField;
-
-  // Accessors
-
-  public Symbol name() {
-    return Symbol.create(nameField.getValue(addr));
-  }
-
-  public int numLoaders() {
-    return (int) numLoadersField.getValue(addr);
-  }
-
-  public int maxLoaders() {
-    return (int) maxLoadersField.getValue(addr);
-  }
-
-  public Oop initiatingLoader(int i) {
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(i >= 0 && i < numLoaders(), "invalid index");
-    }
-    Address loaders = loadersField.getValue(addr);
-    OopHandle loader = loaders.addOffsetToAsOopHandle(i * VM.getVM().getOopSize());
-    return VM.getVM().getObjectHeap().newOop(loader);
-  }
-
-  public LoaderConstraintEntry(Address addr) {
-    super(addr);
-  }
-
-  /* covariant return type :-(
-  public LoaderConstraintEntry next() {
-    return (LoaderConstraintEntry) super.next();
-  }
-  For now, let the caller cast it ..
-  */
-}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java	Mon Aug 21 14:05:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class LoaderConstraintTable extends TwoOopHashtable {
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static synchronized void initialize(TypeDataBase db) {
-    Type type = db.lookupType("LoaderConstraintTable");
-  }
-
-  public LoaderConstraintTable(Address addr) {
-    super(addr);
-  }
-
-  // this is overriden here so that Hashtable.bucket will return
-  // object of LoaderConstraintEntry.class
-  protected Class getHashtableEntryClass() {
-    return LoaderConstraintEntry.class;
-  }
-}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java	Mon Aug 21 14:05:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.classfile.ClassLoaderData;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class PlaceholderEntry extends sun.jvm.hotspot.utilities.HashtableEntry {
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static synchronized void initialize(TypeDataBase db) {
-    Type type = db.lookupType("PlaceholderEntry");
-    loaderDataField = type.getAddressField("_loader_data");
-  }
-
-  // Field
-  private static AddressField loaderDataField;
-
-  // Accessor
-  public Oop loader() {
-    return loaderData().getClassLoader();
-  }
-
-  public ClassLoaderData loaderData() {
-    return ClassLoaderData.instantiateWrapperFor(loaderDataField.getValue(addr));
-  }
-
-  public PlaceholderEntry(Address addr) {
-    super(addr);
-  }
-
-  public Symbol klass() {
-    return Symbol.create(literalValue());
-  }
-
-  /* covariant return type :-(
-  public PlaceholderEntry next() {
-    return (PlaceholderEntry) super.next();
-  }
-  For now, let the caller cast it ..
-  */
-}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderTable.java	Mon Aug 21 14:05:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class PlaceholderTable extends TwoOopHashtable {
-  public PlaceholderTable(Address addr) {
-    super(addr);
-  }
-
-  // this is overriden here so that Hashtable.bucket will return
-  // object of PlacholderEntry.class
-  protected Class getHashtableEntryClass() {
-    return PlaceholderEntry.class;
-  }
-
-  /** All array classes of primitive type, and their class loaders */
-  public void primArrayClassesDo(SystemDictionary.ClassAndLoaderVisitor v) {
-    ObjectHeap heap = VM.getVM().getObjectHeap();
-    int tblSize = tableSize();
-    for (int index = 0; index < tblSize; index++) {
-      for (PlaceholderEntry probe = (PlaceholderEntry) bucket(index); probe != null;
-                                          probe = (PlaceholderEntry) probe.next()) {
-        Symbol sym = probe.klass();
-        // array of primitive arrays are stored in system dictionary as placeholders
-        FieldType ft = new FieldType(sym);
-        if (ft.isArray()) {
-          FieldType.ArrayInfo info = ft.getArrayInfo();
-          if (info.elementBasicType() != BasicType.getTObject()) {
-            Klass arrayKlass = heap.typeArrayKlassObj(info.elementBasicType());
-            arrayKlass = arrayKlass.arrayKlassOrNull(info.dimension());
-            v.visit(arrayKlass, probe.loader());
-          }
-        }
-      }
-    }
-  }
-}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainCacheEntry.java	Mon Aug 21 14:05:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-
-public class ProtectionDomainCacheEntry extends VMObject {
-  private static sun.jvm.hotspot.types.OopField protectionDomainField;
-
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static synchronized void initialize(TypeDataBase db) {
-    Type type = db.lookupType("ProtectionDomainCacheEntry");
-    protectionDomainField = type.getOopField("_literal");
-  }
-
-  public ProtectionDomainCacheEntry(Address addr) {
-    super(addr);
-  }
-
-  public Oop protectionDomain() {
-    return VM.getVM().getObjectHeap().newOop(protectionDomainField.getValue(addr));
-  }
-}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainEntry.java	Mon Aug 21 14:05:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.memory;
-
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-
-public class ProtectionDomainEntry extends VMObject {
-  private static AddressField nextField;
-  private static AddressField pdCacheField;
-
-  static {
-    VM.registerVMInitializedObserver(new Observer() {
-        public void update(Observable o, Object data) {
-          initialize(VM.getVM().getTypeDataBase());
-        }
-      });
-  }
-
-  private static synchronized void initialize(TypeDataBase db) {
-    Type type = db.lookupType("ProtectionDomainEntry");
-
-    nextField = type.getAddressField("_next");
-    pdCacheField = type.getAddressField("_pd_cache");
-  }
-
-  public ProtectionDomainEntry(Address addr) {
-    super(addr);
-  }
-
-  public ProtectionDomainEntry next() {
-    return (ProtectionDomainEntry) VMObjectFactory.newObject(ProtectionDomainEntry.class, nextField.getValue(addr));
-  }
-
-  public Oop protectionDomain() {
-    ProtectionDomainCacheEntry pd_cache = (ProtectionDomainCacheEntry)
-      VMObjectFactory.newObject(ProtectionDomainCacheEntry.class, pdCacheField.getValue(addr));
-    return pd_cache.protectionDomain();
-  }
-}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -26,15 +26,13 @@
 
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.types.*;
 
 public class SystemDictionary {
-  private static AddressField dictionaryField;
   private static AddressField sharedDictionaryField;
-  private static AddressField placeholdersField;
-  private static AddressField loaderConstraintTableField;
   private static sun.jvm.hotspot.types.OopField javaSystemLoaderField;
 
   private static AddressField objectKlassField;
@@ -56,10 +54,7 @@
   private static synchronized void initialize(TypeDataBase db) {
     Type type = db.lookupType("SystemDictionary");
 
-    dictionaryField = type.getAddressField("_dictionary");
     sharedDictionaryField = type.getAddressField("_shared_dictionary");
-    placeholdersField = type.getAddressField("_placeholders");
-    loaderConstraintTableField = type.getAddressField("_loader_constraints");
     javaSystemLoaderField = type.getOopField("_java_system_loader");
 
     objectKlassField = type.getAddressField(WK_KLASS("Object_klass"));
@@ -81,26 +76,11 @@
       return (kname+"_knum");
   }
 
-  public Dictionary dictionary() {
-    Address tmp = dictionaryField.getValue();
-    return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
-  }
-
   public Dictionary sharedDictionary() {
     Address tmp = sharedDictionaryField.getValue();
     return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp);
   }
 
-  public PlaceholderTable placeholders() {
-    Address tmp = placeholdersField.getValue();
-    return (PlaceholderTable) VMObjectFactory.newObject(PlaceholderTable.class, tmp);
-  }
-
-  public LoaderConstraintTable constraints() {
-    Address tmp = placeholdersField.getValue();
-    return (LoaderConstraintTable) VMObjectFactory.newObject(LoaderConstraintTable.class, tmp);
-  }
-
   // few well known classes -- not all are added here.
   // add more if needed.
   public static InstanceKlass getThreadKlass() {
@@ -132,8 +112,8 @@
   }
 
   public InstanceKlass getAbstractOwnableSynchronizerKlass() {
-    return (InstanceKlass) find("java/util/concurrent/locks/AbstractOwnableSynchronizer",
-                                null, null);
+    ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+    return (InstanceKlass) cldg.find("java/util/concurrent/locks/AbstractOwnableSynchronizer");
   }
 
   public static Oop javaSystemLoader() {
@@ -143,60 +123,4 @@
   private static Oop newOop(OopHandle handle) {
     return VM.getVM().getObjectHeap().newOop(handle);
   }
-
-  /** Lookup an already loaded class. If not found null is returned. */
-  public Klass find(String className, Oop classLoader, Oop protectionDomain) {
-    Symbol sym = VM.getVM().getSymbolTable().probe(className);
-    if (sym == null) return null;
-    return find(sym, classLoader, protectionDomain);
-  }
-
-  /** Lookup an already loaded class. If not found null is returned. */
-  public Klass find(Symbol className, Oop classLoader, Oop protectionDomain) {
-    Dictionary dict = dictionary();
-    long hash = dict.computeHash(className, classLoader);
-    int index = dict.hashToIndex(hash);
-    return dict.find(index, hash, className, classLoader, protectionDomain);
-  }
-
-  /** Interface for iterating through all classes in dictionary */
-  public static interface ClassVisitor {
-    public void visit(Klass k);
-  }
-
-  /** Interface for iterating through all classes and their class
-      loaders in dictionary */
-  public static interface ClassAndLoaderVisitor {
-    public void visit(Klass k, Oop loader);
-  }
-
-  /** Iterate over all klasses - including object, primitive
-      array klasses */
-  public void allClassesDo(final ClassVisitor v) {
-    ClassVisitor visitor = new ClassVisitor() {
-      public void visit(Klass k) {
-        for (Klass l = k; l != null; l = l.arrayKlassOrNull()) {
-          v.visit(l);
-        }
-      }
-    };
-    classesDo(visitor);
-    VM.getVM().getUniverse().basicTypeClassesDo(visitor);
-  }
-
-  /** Iterate over all klasses in dictionary; just the classes from
-      declaring class loaders */
-  public void classesDo(ClassVisitor v) {
-    dictionary().classesDo(v);
-  }
-
-  /** All classes, and their class loaders */
-  public void classesDo(ClassAndLoaderVisitor v) {
-    dictionary().classesDo(v);
-  }
-
-  /** All array classes of primitive type, and their class loaders */
-  public void primArrayClassesDo(ClassAndLoaderVisitor v) {
-    placeholders().primArrayClassesDo(v);
-  }
 }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -164,18 +164,6 @@
     return newOop(systemThreadGroupField.getValue());
   }
 
-  // iterate through the single dimensional primitive array klasses
-  // refer to basic_type_classes_do(void f(Klass*)) in universe.cpp
-  public void basicTypeClassesDo(SystemDictionary.ClassVisitor visitor) {
-    visitor.visit(new TypeArrayKlass(boolArrayKlassField.getValue()));
-    visitor.visit(new TypeArrayKlass(byteArrayKlassField.getValue()));
-    visitor.visit(new TypeArrayKlass(charArrayKlassField.getValue()));
-    visitor.visit(new TypeArrayKlass(intArrayKlassField.getValue()));
-    visitor.visit(new TypeArrayKlass(shortArrayKlassField.getValue()));
-    visitor.visit(new TypeArrayKlass(longArrayKlassField.getValue()));
-    visitor.visit(new TypeArrayKlass(singleArrayKlassField.getValue()));
-    visitor.visit(new TypeArrayKlass(doubleArrayKlassField.getValue()));
-  }
 
   public void print() { printOn(System.out); }
   public void printOn(PrintStream tty) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Thu Aug 24 09:44:52 2017 +0200
@@ -91,7 +91,6 @@
     fields               = type.getAddressField("_fields");
     javaFieldsCount      = new CIntField(type.getCIntegerField("_java_fields_count"), 0);
     constants            = new MetadataField(type.getAddressField("_constants"), 0);
-    classLoaderData      = type.getAddressField("_class_loader_data");
     sourceDebugExtension = type.getAddressField("_source_debug_extension");
     innerClasses         = type.getAddressField("_inner_classes");
     sourceFileNameIndex  = new CIntField(type.getCIntegerField("_source_file_name_index"), 0);
@@ -166,7 +165,6 @@
   private static AddressField fields;
   private static CIntField javaFieldsCount;
   private static MetadataField constants;
-  private static AddressField  classLoaderData;
   private static AddressField  sourceDebugExtension;
   private static AddressField  innerClasses;
   private static CIntField sourceFileNameIndex;
@@ -328,7 +326,7 @@
       // MetaspaceObj in the CDS shared archive.
       Dictionary sharedDictionary = vm.getSystemDictionary().sharedDictionary();
       if (sharedDictionary != null) {
-        if (sharedDictionary.contains(this, null)) {
+        if (sharedDictionary.contains(this)) {
           return true;
         }
       }
@@ -448,8 +446,6 @@
     return allFieldsCount;
   }
   public ConstantPool getConstants()        { return (ConstantPool) constants.getValue(this); }
-  public ClassLoaderData getClassLoaderData() { return                ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); }
-  public Oop       getClassLoader()         { return                getClassLoaderData().getClassLoader(); }
   public Symbol    getSourceFileName()      { return                getConstants().getSymbolAt(sourceFileNameIndex.getValue(this)); }
   public String    getSourceDebugExtension(){ return                CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
   public long      getNonstaticFieldSize()  { return                nonstaticFieldSize.getValue(this); }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -27,6 +27,7 @@
 import java.io.*;
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.runtime.*;
 import sun.jvm.hotspot.types.*;
 
@@ -63,6 +64,7 @@
     nextSibling  = new MetadataField(type.getAddressField("_next_sibling"), 0);
     nextLink     = new MetadataField(type.getAddressField("_next_link"), 0);
     vtableLen    = new CIntField(type.getCIntegerField("_vtable_len"), 0);
+    classLoaderData = type.getAddressField("_class_loader_data");
 
     LH_INSTANCE_SLOW_PATH_BIT  = db.lookupIntConstant("Klass::_lh_instance_slow_path_bit").intValue();
     LH_LOG2_ELEMENT_SIZE_SHIFT = db.lookupIntConstant("Klass::_lh_log2_element_size_shift").intValue();
@@ -96,6 +98,7 @@
   private static MetadataField  nextLink;
   private static sun.jvm.hotspot.types.Field traceIDField;
   private static CIntField vtableLen;
+  private static AddressField classLoaderData;
 
   private Address getValue(AddressField field) {
     return addr.getAddressAt(field.getOffset());
@@ -110,7 +113,7 @@
   public Klass    getSuper()            { return (Klass)    superField.getValue(this);   }
   public Klass    getJavaSuper()        { return null;  }
   public int      getLayoutHelper()     { return (int)           layoutHelper.getValue(this); }
-  public Symbol   getName()             { return getSymbol(name); }
+  public Symbol   getName()             { return            getSymbol(name); }
   public long     getAccessFlags()      { return            accessFlags.getValue(this);  }
   // Convenience routine
   public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags());      }
@@ -119,6 +122,9 @@
   public Klass    getNextLinkKlass()    { return (Klass)    nextLink.getValue(this);  }
   public long     getVtableLen()        { return            vtableLen.getValue(this); }
 
+  public ClassLoaderData getClassLoaderData() { return ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); }
+  public Oop             getClassLoader()     { return   getClassLoaderData().getClassLoader(); }
+
   public long traceID() {
     if (traceIDField == null) return 0;
     return traceIDField.getJLong(addr);
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -108,13 +108,16 @@
 
     public Object next() {
       Address addr;
-      if (index > 0) {
-        addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
-      } else {
+      if (index == 0) {
+        // advance to next block
         blockAddr = block.freeNext();
+        if (blockAddr == null) {
+          throw new NoSuchElementException();
+        }
+        block = new ObjectMonitor(blockAddr);
         index = blockSize - 1;
-        addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
       }
+      addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize);
       index --;
       return new ObjectMonitor(addr);
     }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, 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
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
@@ -106,8 +107,8 @@
          err.print("computing per loader stat ..");
       }
 
-      SystemDictionary dict = VM.getVM().getSystemDictionary();
-      dict.classesDo(new SystemDictionary.ClassVisitor() {
+      ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+      cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
                         public void visit(Klass k) {
                            if (! (k instanceof InstanceKlass)) {
                               return;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, 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
@@ -29,6 +29,7 @@
 import java.util.jar.JarOutputStream;
 import java.util.jar.JarEntry;
 import java.util.jar.Manifest;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.debugger.*;
@@ -100,9 +101,9 @@
                 setOutputDirectory(dirName);
             }
 
-            // walk through the system dictionary
-            SystemDictionary dict = VM.getVM().getSystemDictionary();
-            dict.classesDo(new SystemDictionary.ClassVisitor() {
+            // walk through the loaded classes
+            ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+            cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
                     public void visit(Klass k) {
                         if (k instanceof InstanceKlass) {
                             try {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, 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
@@ -27,6 +27,7 @@
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
 
 public class Hashtable extends BasicHashtable {
@@ -48,6 +49,10 @@
     return HashtableEntry.class;
   }
 
+  public int computeHash(Symbol name) {
+    return (int) name.identityHash();
+  }
+
   public int hashToIndex(long fullHash) {
     return (int) (fullHash % tableSize());
   }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java	Thu Aug 24 09:44:52 2017 +0200
@@ -586,23 +586,9 @@
     }
 
     private void writeClassDumpRecords() throws IOException {
-        SystemDictionary sysDict = VM.getVM().getSystemDictionary();
         ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
         try {
-            sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
-                            public void visit(Klass k) {
-                                try {
-                                    writeHeapRecordPrologue();
-                                    writeClassDumpRecord(k);
-                                    writeHeapRecordEpilogue();
-                                } catch (IOException e) {
-                                    throw new RuntimeException(e);
-                                }
-                            }
-                        });
-             // Add the anonymous classes also which are not present in the
-             // System Dictionary
-             cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
+             cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
                             public void visit(Klass k) {
                                 try {
                                     writeHeapRecordPrologue();
@@ -1088,26 +1074,9 @@
 
     private void writeClasses() throws IOException {
         // write class list (id, name) association
-        SystemDictionary sysDict = VM.getVM().getSystemDictionary();
         ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
         try {
-            sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
-                public void visit(Klass k) {
-                    try {
-                        Instance clazz = k.getJavaMirror();
-                        writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
-                        out.writeInt(serialNum);
-                        writeObjectID(clazz);
-                        KlassMap.add(serialNum - 1, k);
-                        out.writeInt(DUMMY_STACK_TRACE_ID);
-                        writeSymbolID(k.getName());
-                        serialNum++;
-                    } catch (IOException exp) {
-                        throw new RuntimeException(exp);
-                    }
-                }
-            });
-            cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() {
+            cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
                 public void visit(Klass k) {
                     try {
                         Instance clazz = k.getJavaMirror();
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, 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
@@ -27,6 +27,7 @@
 import java.io.*;
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.gc.shared.*;
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
@@ -113,8 +114,8 @@
                      new RootVisitor("Weak global JNI handle root"));
 
     // Do Java-level static fields
-    SystemDictionary sysDict = VM.getVM().getSystemDictionary();
-    sysDict.allClassesDo(new SystemDictionary.ClassVisitor() {
+    ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+    cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
 
             public void visit(Klass k) {
                 if (k instanceof InstanceKlass) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2005, 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
@@ -25,6 +25,7 @@
 package sun.jvm.hotspot.utilities;
 
 import java.util.*;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.runtime.*;
@@ -52,8 +53,8 @@
       }
 
       final Vector tmp = new Vector();
-      SystemDictionary dict = VM.getVM().getSystemDictionary();
-      dict.classesDo(new SystemDictionary.ClassVisitor() {
+      ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
+      cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
                         public void visit(Klass k) {
                            if (k instanceof InstanceKlass) {
                               InstanceKlass ik = (InstanceKlass) k;
@@ -100,42 +101,15 @@
    public static InstanceKlass findInstanceKlass(String className) {
       // convert to internal name
       className = className.replace('.', '/');
-      SystemDictionary sysDict = VM.getVM().getSystemDictionary();
+      ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
 
-      // check whether we have a bootstrap class of given name
-      Klass klass = sysDict.find(className, null, null);
-      if (klass != null) {
+      // check whether we have a class of given name
+      Klass klass = cldg.find(className);
+      if (klass != null && klass instanceof InstanceKlass) {
          return (InstanceKlass) klass;
+      } else {
+        // no match ..
+        return null;
       }
-
-      // check whether we have a system class of given name
-      klass = sysDict.find(className, sysDict.javaSystemLoader(), null);
-      if (klass != null) {
-         return (InstanceKlass) klass;
-      }
-
-      // didn't find bootstrap or system class of given name.
-      // search through the entire dictionary..
-      InstanceKlass[] tmpKlasses = getAllInstanceKlasses();
-      // instance klass array is sorted by name. do binary search
-      int low = 0;
-      int high = tmpKlasses.length-1;
-
-      int mid = -1;
-      while (low <= high) {
-         mid = (low + high) >> 1;
-         InstanceKlass midVal = tmpKlasses[mid];
-         int cmp = midVal.getName().asString().compareTo(className);
-
-         if (cmp < 0) {
-             low = mid + 1;
-         } else if (cmp > 0) {
-             high = mid - 1;
-         } else { // match found
-             return tmpKlasses[mid];
-         }
-      }
-      // no match ..
-      return null;
    }
 }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/TwoOopHashtable.java	Mon Aug 21 14:05:14 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package sun.jvm.hotspot.utilities;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-
-public class TwoOopHashtable extends Hashtable {
-  public TwoOopHashtable(Address addr) {
-    super(addr);
-  }
-
-  public long computeHash(Symbol name, Oop loader) {
-    return ((int) name.identityHash()
-        ^  (int) (loader == null ? 0 : loader.identityHash())) & 0xFFFFFFFFL;
-  }
-
-  public int indexFor(Symbol name, Oop loader) {
-    return hashToIndex(computeHash(name, loader));
-  }
-}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaHeap.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaHeap.java	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -27,6 +27,7 @@
 import java.util.*;
 import javax.script.ScriptException;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.classfile.*;
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
@@ -166,11 +167,12 @@
         }
 
       final Callable finalFunc = func;
-        SystemDictionary sysDict = VM.getVM().getSystemDictionary();
+        ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
         if (withLoader) {
-            sysDict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() {
-                    public void visit(Klass kls, Oop loader) {
+            cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
+                    public void visit(Klass kls) {
                         JSJavaKlass  jk = factory.newJSJavaKlass(kls);
+                        Oop loader = kls.getClassLoader();
                         if (jk == null) {
                             return;
                         }
@@ -189,7 +191,7 @@
                 });
 
         } else {
-            sysDict.classesDo(new SystemDictionary.ClassVisitor() {
+            cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
                     public void visit(Klass kls) {
                         JSJavaKlass jk = factory.newJSJavaKlass(kls);
                         if (jk == null) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js	Thu Aug 24 09:44:52 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -513,24 +513,18 @@
    return sa.sysDict.javaSystemLoader();
 }
 
-// iterate system dictionary for each 'Klass' 
+// iterate class loader data for each 'Klass' 
 function forEachKlass(callback) {
-   var VisitorClass = sapkg.memory.SystemDictionary.ClassVisitor;
+   var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassVisitor;
    var visitor = new VisitorClass() { visit: callback };
-   sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassVisitor)"](visitor);
+   sa.sysDict["classesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassVisitor)"](visitor);
 }
 
 // iterate system dictionary for each 'Klass' and initiating loader
 function forEachKlassAndLoader(callback) {
-   var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor;
+   var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor;
    var visitor = new VisitorClass() { visit: callback };
-   sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassAndLoaderVisitor)"](visitor);
-}
-
-// iterate system dictionary for each primitive array klass
-function forEachPrimArrayKlass(callback) {
-   var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor;
-   sa.sysDict.primArrayClassesDo(new VisitorClass() { visit: callback });
+   sa.sysDict["allEntriesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor)"](visitor);
 }
 
 // 'oop' to higher-level java object wrapper in which for(i in o) 
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Thu Aug 24 09:44:52 2017 +0200
@@ -39,7 +39,7 @@
     private Set<SpeculationReason> failedSpeculations;
 
     /** Strong references to all reasons embedded in the current nmethod. */
-    private volatile Collection<SpeculationReason> speculations;
+    private Collection<SpeculationReason> speculations;
 
     @Override
     public synchronized void collectFailedSpeculations() {
@@ -70,14 +70,12 @@
          * reason objects that are embedded in nmethods, so we add them to the speculations
          * collection.
          */
-        if (speculations == null) {
-            synchronized (this) {
-                if (speculations == null) {
-                    speculations = new ConcurrentLinkedQueue<>();
-                }
+        synchronized (this) {
+            if (speculations == null) {
+                speculations = new ConcurrentLinkedQueue<>();
             }
+            speculations.add(reason);
         }
-        speculations.add(reason);
 
         return HotSpotObjectConstantImpl.forObject(reason);
     }
--- a/src/jdk.internal.vm.compiler/.mx.graal/suite.py	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/.mx.graal/suite.py	Thu Aug 24 09:44:52 2017 +0200
@@ -179,6 +179,14 @@
       "workingSets" : "Graal",
     },
 
+    "org.graalvm.graphio" : {
+      "subDir" : "share/classes",
+      "sourceDirs" : ["src"],
+      "checkstyle" : "org.graalvm.compiler.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,Graal",
+    },
+
     "org.graalvm.util" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
@@ -1011,6 +1019,7 @@
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
       "dependencies" : [
+        "org.graalvm.graphio",
         "org.graalvm.compiler.core",
         "org.graalvm.compiler.java",
       ],
@@ -1138,6 +1147,13 @@
       ],
     },
 
+    "GRAAL_GRAPHIO" : {
+      "subDir" : "share/classes",
+      "dependencies" : ["org.graalvm.graphio"],
+      "distDependencies" : [
+      ],
+    },
+
     "GRAAL_OPTIONS_PROCESSOR" : {
       "subDir" : "share/classes",
       "dependencies" : ["org.graalvm.compiler.options.processor"],
@@ -1203,6 +1219,7 @@
       "distDependencies" : [
         "GRAAL_API",
         "GRAAL_COMPILER",
+        "GRAAL_GRAPHIO",
       ],
     },
 
@@ -1297,6 +1314,7 @@
     "GRAAL" : {
       "subDir" : "share/classes",
       "overlaps" : [
+        "GRAAL_GRAPHIO",
         "GRAAL_OPTIONS",
         "GRAAL_NODEINFO",
         "GRAAL_API",
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java	Thu Aug 24 09:44:52 2017 +0200
@@ -94,7 +94,7 @@
         }
     }
 
-    protected Value emitExtendMemory(boolean isSigned, AArch64Kind memoryKind, int resultBits, AArch64AddressValue address, LIRFrameState state) {
+    public Value emitExtendMemory(boolean isSigned, AArch64Kind memoryKind, int resultBits, AArch64AddressValue address, LIRFrameState state) {
         // Issue a zero extending load of the proper bit size and set the result to
         // the proper kind.
         Variable result = getLIRGen().newVariable(LIRKind.value(resultBits == 32 ? AArch64Kind.DWORD : AArch64Kind.QWORD));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Thu Aug 24 09:44:52 2017 +0200
@@ -24,14 +24,9 @@
 package org.graalvm.compiler.core.aarch64;
 
 import org.graalvm.compiler.core.gen.NodeMatchRules;
-import org.graalvm.compiler.core.match.ComplexMatchResult;
-import org.graalvm.compiler.core.match.MatchRule;
 import org.graalvm.compiler.lir.LIRFrameState;
-import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodes.DeoptimizingNode;
-import org.graalvm.compiler.nodes.calc.SignExtendNode;
-import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
 import org.graalvm.compiler.nodes.memory.Access;
 
 import jdk.vm.ci.aarch64.AArch64Kind;
@@ -61,18 +56,4 @@
     protected AArch64ArithmeticLIRGenerator getArithmeticLIRGenerator() {
         return (AArch64ArithmeticLIRGenerator) getLIRGeneratorTool().getArithmetic();
     }
-
-    @MatchRule("(ZeroExtend Read=access)")
-    @MatchRule("(ZeroExtend FloatingRead=access)")
-    public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) {
-        AArch64Kind memoryKind = getMemoryKind(access);
-        return builder -> getArithmeticLIRGenerator().emitExtendMemory(false, memoryKind, root.getResultBits(), (AArch64AddressValue) operand(access.getAddress()), getState(access));
-    }
-
-    @MatchRule("(SignExtend Read=access)")
-    @MatchRule("(SignExtend FloatingRead=access)")
-    public ComplexMatchResult signExtend(SignExtendNode root, Access access) {
-        AArch64Kind memoryKind = getMemoryKind(access);
-        return builder -> getArithmeticLIRGenerator().emitExtendMemory(true, memoryKind, root.getResultBits(), (AArch64AddressValue) operand(access.getAddress()), getState(access));
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,7 +22,6 @@
  */
 package org.graalvm.compiler.core.common;
 
-import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionType;
@@ -269,9 +268,6 @@
     @Option(help = "Use a cache for snippet graphs.", type = OptionType.Debug)
     public static final OptionKey<Boolean> UseSnippetGraphCache = new OptionKey<>(true);
 
-    @Option(help = "Enable expensive assertions.", type = OptionType.Debug)
-    public static final OptionKey<Boolean> DetailedAsserts = new OptionKey<>(Assertions.ENABLED);
-
     @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug)
     public static final OptionKey<Boolean> TraceRA = new OptionKey<>(false);
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java	Thu Aug 24 09:44:52 2017 +0200
@@ -71,6 +71,7 @@
             field.setAccessible(true);
             enabled = field.get(null) != null;
         } catch (Exception e) {
+        } catch (LinkageError e) {
         }
         ENABLED = enabled;
         if (ENABLED) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Thu Aug 24 09:44:52 2017 +0200
@@ -101,6 +101,14 @@
  */
 public class CheckGraalInvariants extends GraalCompilerTest {
 
+    public CheckGraalInvariants() {
+        try {
+            Class.forName("java.lang.management.ManagementFactory");
+        } catch (ClassNotFoundException ex) {
+            Assume.assumeNoException("cannot run without java.management JDK9 module", ex);
+        }
+    }
+
     private static boolean shouldVerifyEquals(ResolvedJavaMethod m) {
         if (m.getName().equals("identityEquals")) {
             ResolvedJavaType c = m.getDeclaringClass();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -111,6 +111,7 @@
 import org.graalvm.compiler.phases.schedule.SchedulePhase;
 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.graalvm.compiler.phases.tiers.MidTierContext;
 import org.graalvm.compiler.phases.tiers.Suites;
 import org.graalvm.compiler.phases.tiers.TargetProvider;
 import org.graalvm.compiler.phases.util.Providers;
@@ -595,6 +596,10 @@
         return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
     }
 
+    protected MidTierContext getDefaultMidTierContext() {
+        return new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, null);
+    }
+
     protected SnippetReflectionProvider getSnippetReflection() {
         return Graal.getRequiredCapability(SnippetReflectionProvider.class);
     }
@@ -926,7 +931,7 @@
      */
     @SuppressWarnings("try")
     protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) {
-        if (!forceCompile) {
+        if (!forceCompile && graph == null) {
             InstalledCode cached = cache.get(installedCodeOwner);
             if (cached != null) {
                 if (cached.isValid()) {
@@ -941,6 +946,7 @@
             InstalledCode installedCode = null;
             StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, id, options) : graph;
             DebugContext debug = graphToCompile.getDebug();
+
             try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) {
                 CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI);
                 CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(), id, options);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ZeroSignExtendTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+package org.graalvm.compiler.core.test;
+
+import org.junit.Test;
+
+/*
+ * Test compilation of ZeroExtend and SignExtend nodes
+ */
+
+public class ZeroSignExtendTest extends GraalCompilerTest {
+
+    int testSnippet1(char[] chars) {
+        int x = 1;
+        x += chars[0];
+        x -= chars[1];
+        x *= chars[2];
+        x /= chars[3];
+        x &= chars[4];
+        x |= chars[5];
+        x ^= chars[6];
+        x <<= chars[7];
+        x >>= (chars[8] - chars[0]);
+        x >>>= (chars[9] - chars[0]);
+        x += chars[1];
+        return x;
+    }
+
+    long testSnippet2(char[] chars) {
+        long y = 2;
+        y += chars[0];
+        y -= chars[1];
+        y *= chars[2];
+        y /= chars[3];
+        y &= chars[4];
+        y |= chars[5];
+        y ^= chars[6];
+        y <<= chars[7];
+        y >>= (chars[8] - chars[0]);
+        y >>>= (chars[9] - chars[0]);
+        y += chars[1];
+        return y;
+    }
+
+    int testSnippet3(short[] shorts) {
+        int x = 1;
+        x += shorts[0];
+        x -= shorts[1];
+        x *= shorts[2];
+        x /= shorts[3];
+        x &= shorts[4];
+        x |= shorts[5];
+        x ^= shorts[6];
+        x <<= shorts[7];
+        x >>= (shorts[8] - shorts[0]);
+        x >>>= (shorts[9] - shorts[0]);
+        x += shorts[1];
+        return x;
+    }
+
+    long testSnippet4(short[] shorts) {
+        long y = 2;
+        y += shorts[0];
+        y -= shorts[1];
+        y *= shorts[2];
+        y /= shorts[3];
+        y &= shorts[4];
+        y |= shorts[5];
+        y ^= shorts[6];
+        y <<= shorts[7];
+        y >>= (shorts[8] - shorts[0]);
+        y >>>= (shorts[9] - shorts[0]);
+        y += shorts[1];
+        return y;
+    }
+
+    int testSnippet5(byte[] bytes) {
+        int x = 1;
+        x += bytes[0];
+        x -= bytes[1];
+        x *= bytes[2];
+        x /= bytes[3];
+        x &= bytes[4];
+        x |= bytes[5];
+        x ^= bytes[6];
+        x <<= bytes[7];
+        x >>= (bytes[8] - bytes[0]);
+        x >>>= (bytes[9] - bytes[0]);
+        x += bytes[1];
+        return x;
+    }
+
+    long testSnippet6(byte[] bytes) {
+        long y = 2;
+        y += bytes[0];
+        y -= bytes[1];
+        y *= bytes[2];
+        y /= bytes[3];
+        y &= bytes[4];
+        y |= bytes[5];
+        y ^= bytes[6];
+        y <<= bytes[7];
+        y >>= (bytes[8] - bytes[0]);
+        y >>>= (bytes[9] - bytes[0]);
+        y += bytes[1];
+        return y;
+    }
+
+    @Test
+
+    public void test() {
+        char[] input1 = new char[]{'0', '1', '2', '3', '4', '5', '7', '8', '9', 'A'};
+        char[] input2 = new char[]{'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'};
+
+        short[] input3 = new short[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        short[] input4 = new short[]{11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
+
+        byte[] input5 = new byte[]{21, 22, 23, 24, 25, 26, 27, 28, 29, 30};
+        byte[] input6 = new byte[]{11, 12, 13, 14, 15, 16, 17, 18, 19, 40};
+
+        test("testSnippet1", input1);
+        test("testSnippet2", input2);
+        test("testSnippet3", input3);
+        test("testSnippet4", input4);
+        test("testSnippet5", input5);
+        test("testSnippet6", input6);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/CountUppercaseParallelTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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.
+ */
+package org.graalvm.compiler.core.test.ea;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.junit.Test;
+
+public class CountUppercaseParallelTest extends GraalCompilerTest {
+    public static long count(CharSequence sentence) {
+        return sentence.chars().parallel().filter(c -> Character.isUpperCase(c)).count();
+    }
+
+    @Test
+    public void testCount() {
+        String sequence = "In 2017 I would like to run ALL languages in one VM.";
+        for (int i = 0; i < 5000; i++) {
+            count(sequence);
+        }
+        test("count", sequence);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTreesTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 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.
+ */
+package org.graalvm.compiler.core.test.ea;
+
+import java.util.HashSet;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.nodes.debug.BlackholeNode;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/*
+ * Test whether complex tree structures properly maintain identity.
+ */
+public class PartialEscapeAnalysisTreesTest extends EATestBase {
+
+    static class TreeNode {
+        TreeNode left;
+        TreeNode right;
+
+        TreeNode() {
+
+        }
+
+        TreeNode(TreeNode left, TreeNode right) {
+            this.left = left;
+            this.right = right;
+        }
+
+        public void visit(HashSet<TreeNode> instances) {
+            instances.add(this);
+            if (left != null) {
+                left.visit(instances);
+            }
+            if (right != null) {
+                right.visit(instances);
+            }
+        }
+
+        int countInstances() {
+            HashSet<TreeNode> instances = new HashSet<>();
+            visit(instances);
+            return instances.size();
+        }
+    }
+
+    public static TreeNode buildTree(boolean a) {
+        TreeNode leftChild;
+        TreeNode rightChild;
+        TreeNode taskToFork;
+        TreeNode task;
+        if (a) {
+            GraalDirectives.blackhole(new TreeNode());
+            leftChild = new TreeNode();
+            rightChild = new TreeNode();
+            task = new TreeNode(leftChild, rightChild);
+            taskToFork = rightChild;
+            GraalDirectives.blackhole(task);
+        } else {
+            leftChild = new TreeNode();
+            rightChild = new TreeNode();
+            task = new TreeNode(leftChild, rightChild);
+            taskToFork = leftChild;
+            GraalDirectives.blackhole(task);
+        }
+        if (taskToFork.left == null) {
+            taskToFork.left = new TreeNode();
+        }
+
+        return new TreeNode(task, null);
+    }
+
+    @Test
+    public void testBuildTree() {
+        testGraph("buildTree");
+    }
+
+    /**
+     * Prepare a graph that includes some blackholes and then remove the blackholes and compile
+     * normally to create an unusual situation for PEA.
+     */
+    @SuppressWarnings("try")
+    public void testGraph(String name) {
+        ResolvedJavaMethod method = getResolvedJavaMethod(name);
+
+        prepareGraph(name, true);
+        try (DebugContext.Scope s = graph.getDebug().scope(getClass(), method, getCodeCache(), graph)) {
+            for (BlackholeNode node : graph.getNodes().filter(BlackholeNode.class)) {
+                graph.removeFixed(node);
+            }
+            new DeadCodeEliminationPhase().apply(graph);
+            new CanonicalizerPhase().apply(graph, context);
+
+            InstalledCode code = getCode(method, graph, true);
+
+            GraalCompilerTest.Result r = executeExpected(method, null, true);
+            int expectedInstances = ((TreeNode) r.returnValue).countInstances();
+            TreeNode r2 = (TreeNode) code.executeVarargs(true);
+            Assert.assertEquals("Wrong number of nodes in tree", expectedInstances, r2.countInstances());
+
+            r = executeExpected(method, null, false);
+            expectedInstances = ((TreeNode) r.returnValue).countInstances();
+            r2 = (TreeNode) code.executeVarargs(false);
+            Assert.assertEquals("Wrong number of nodes in tree", expectedInstances, r2.countInstances());
+        } catch (Throwable e) {
+            throw graph.getDebug().handle(e);
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -38,6 +38,10 @@
     private static final long fieldOffset1;
     private static final long fieldOffset2;
 
+    private static final long byteArrayBaseOffset;
+    private static final long intArrayBaseOffset;
+    private static final long longArrayBaseOffset;
+
     static {
         try {
             long localFieldOffset1 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("x"));
@@ -51,6 +55,9 @@
                 fieldOffset2 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("z"));
             }
             assert fieldOffset2 == fieldOffset1 + 4;
+            byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class);
+            intArrayBaseOffset = UNSAFE.arrayBaseOffset(int[].class);
+            longArrayBaseOffset = UNSAFE.arrayBaseOffset(long[].class);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
@@ -195,4 +202,77 @@
         }
         return x;
     }
+
+    public static int testWriteIntToByteArraySnippet() {
+        byte[] array = new byte[4];
+        UNSAFE.putInt(array, byteArrayBaseOffset, 0x01020304);
+        return array[0];
+    }
+
+    @Test
+    public void testWriteIntToByteArray() {
+        test("testWriteIntToByteArraySnippet");
+    }
+
+    public static byte testWriteSignedExtendedByteToByteArraySnippet(byte b) {
+        byte[] array = new byte[4];
+        array[0] = 0x01;
+        array[1] = 0x02;
+        array[2] = 0x03;
+        array[3] = 0x04;
+        UNSAFE.putInt(array, byteArrayBaseOffset, b);
+        return array[3];
+    }
+
+    @Test
+    public void testWriteSignedExtendedByteToByteArray() {
+        test("testWriteSignedExtendedByteToByteArraySnippet", (byte) 0);
+    }
+
+    public static int testWriteLongToIntArraySnippet() {
+        int[] array = new int[2];
+        UNSAFE.putLong(array, intArrayBaseOffset, 0x0102030405060708L);
+        return array[0];
+    }
+
+    @Test
+    public void testWriteLongToIntArray() {
+        test("testWriteLongToIntArraySnippet");
+    }
+
+    public static int testWriteByteToIntArraySnippet() {
+        int[] array = new int[1];
+        array[0] = 0x01020304;
+        UNSAFE.putByte(array, intArrayBaseOffset, (byte) 0x05);
+        return array[0];
+    }
+
+    @Test
+    public void testWriteByteToIntArray() {
+        test("testWriteByteToIntArraySnippet");
+    }
+
+    public static long testWriteIntToLongArraySnippet() {
+        long[] array = new long[1];
+        array[0] = 0x0102030405060708L;
+        UNSAFE.putInt(array, longArrayBaseOffset, 0x04030201);
+        return array[0];
+    }
+
+    @Test
+    public void testWriteIntToLongArray() {
+        test("testWriteIntToLongArraySnippet");
+    }
+
+    public static float testWriteFloatToIntArraySnippet() {
+        float[] array = new float[1];
+        UNSAFE.putInt(array, intArrayBaseOffset, Float.floatToRawIntBits(0.5f));
+        return array[0];
+    }
+
+    @Test
+    public void testWriteFloatToIntArray() {
+        test("testWriteFloatToIntArraySnippet");
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Thu Aug 24 09:44:52 2017 +0200
@@ -26,6 +26,7 @@
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
+import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
 import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL;
 import static org.graalvm.compiler.debug.DebugOptions.Dump;
 import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
@@ -36,6 +37,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
+import java.util.Map;
 
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
@@ -59,6 +61,8 @@
      * {@link CompilationWrapper}. The actions are with respect to what the user sees on the
      * console. The compilation requester determines what ultimate action is taken in
      * {@link CompilationWrapper#handleException(Throwable)}.
+     *
+     * The actions are in ascending order of verbosity.
      */
     public enum ExceptionAction {
         /**
@@ -97,16 +101,32 @@
                 return null;
             }
         }
+
+        /**
+         * Gets the action that is one level less verbose than this action, bottoming out at the
+         * least verbose action.
+         */
+        ExceptionAction quieter() {
+            assert ExceptionAction.Silent.ordinal() == 0;
+            int index = Math.max(ordinal() - 1, 0);
+            return values()[index];
+        }
     }
 
     private final DiagnosticsOutputDirectory outputDirectory;
 
+    private final Map<ExceptionAction, Integer> problemsHandledPerAction;
+
     /**
      * @param outputDirectory object used to access a directory for dumping if the compilation is
      *            re-executed
+     * @param problemsHandledPerAction map used to count the number of compilation failures or
+     *            bailouts handled by each action. This is provided by the caller as it is expected
+     *            to be shared between instances of {@link CompilationWrapper}.
      */
-    public CompilationWrapper(DiagnosticsOutputDirectory outputDirectory) {
+    public CompilationWrapper(DiagnosticsOutputDirectory outputDirectory, Map<ExceptionAction, Integer> problemsHandledPerAction) {
         this.outputDirectory = outputDirectory;
+        this.problemsHandledPerAction = problemsHandledPerAction;
     }
 
     /**
@@ -177,9 +197,12 @@
             }
             ExceptionAction action = lookupAction(initialOptions, actionKey);
 
+            action = adjustAction(initialOptions, actionKey, action);
+
             if (action == ExceptionAction.Silent) {
                 return handleException(cause);
             }
+
             if (action == ExceptionAction.Print) {
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 try (PrintStream ps = new PrintStream(baos)) {
@@ -214,7 +237,7 @@
 
             String dir = this.outputDirectory.getPath();
             if (dir == null) {
-                return null;
+                return handleException(cause);
             }
             String dumpName = PathUtilities.sanitizeFileName(toString());
             File dumpPath = new File(dir, dumpName);
@@ -274,4 +297,31 @@
             }
         }
     }
+
+    /**
+     * Adjusts {@code initialAction} if necessary based on
+     * {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
+     */
+    private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
+        ExceptionAction action = initialAction;
+        int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
+        synchronized (problemsHandledPerAction) {
+            while (action != ExceptionAction.Silent) {
+                int problems = problemsHandledPerAction.getOrDefault(action, 0);
+                if (problems >= maxProblems) {
+                    if (problems == maxProblems) {
+                        TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(),
+                                        MaxCompilationProblemsPerAction, maxProblems);
+                        // Ensure that the message above is only printed once
+                        problemsHandledPerAction.put(action, problems + 1);
+                    }
+                    action = action.quieter();
+                } else {
+                    break;
+                }
+            }
+            problemsHandledPerAction.put(action, problemsHandledPerAction.getOrDefault(action, 0) + 1);
+        }
+        return action;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Thu Aug 24 09:44:52 2017 +0200
@@ -39,11 +39,14 @@
     @Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " +
                    "This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug)
     public static final OptionKey<String> CrashAt = new OptionKey<>(null);
-    @Option(help = "Specifies the action to take when compilation fails with a non-bailout exception.", type = OptionType.User)
+    @Option(help = "The action to take when compilation fails with a non-bailout exception.", type = OptionType.User)
     public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose, ExceptionAction.HELP);
-    @Option(help = "Specifies the action to take when compilation fails with a bailout exception.", type = OptionType.User)
+    @Option(help = "The action to take when compilation fails with a bailout exception.", type = OptionType.User)
     public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent, ExceptionAction.HELP);
-    @Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.Debug)
+    @Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " +
+                   "by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action.", type = OptionType.User)
+    public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(5);
+    @Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User)
     public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false);
     // @formatter:on
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -227,7 +227,7 @@
      */
     @Test
     public void testInvariantChecking() throws InterruptedException {
-        Assume.assumeTrue(Assertions.ENABLED);
+        Assume.assumeTrue(Assertions.assertionsEnabled());
         EconomicMap<OptionKey<?>, Object> map = EconomicMap.create();
         // Configure with an option that enables counters
         map.put(DebugOptions.Counters, "");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -45,11 +45,14 @@
 @SuppressWarnings("try")
 public class TimerKeyTest {
 
-    private static final ThreadMXBean threadMXBean = Management.getThreadMXBean();
-
     @Before
     public void checkCapabilities() {
-        Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported());
+        try {
+            ThreadMXBean threadMXBean = Management.getThreadMXBean();
+            Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported());
+        } catch (LinkageError err) {
+            Assume.assumeNoException("Cannot run without java.management JDK9 module", err);
+        }
     }
 
     /**
@@ -60,6 +63,7 @@
      *         {@code ms}
      */
     private static long spin(long ms) {
+        ThreadMXBean threadMXBean = Management.getThreadMXBean();
         long start = threadMXBean.getCurrentThreadCpuTime();
         do {
             long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,6 +22,11 @@
  */
 package org.graalvm.compiler.debug;
 
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
+import org.graalvm.compiler.options.OptionValues;
+
 /**
  * Utility for query whether assertions are enabled.
  */
@@ -30,11 +35,28 @@
      * Determines if assertions are enabled. Strictly speaking, this may only be true for the
      * {@link Assertions} class but we assume assertions are enabled/disabled for Graal as a whole.
      */
-    public static final boolean ENABLED = assertionsEnabled();
-
-    private static boolean assertionsEnabled() {
+    public static boolean assertionsEnabled() {
         boolean enabled = false;
         assert (enabled = true) == true;
         return enabled;
     }
+
+    /**
+     * Determines if detailed assertions are enabled. This requires that the normal assertions are
+     * also enabled.
+     *
+     * @param values the current OptionValues that might define a value for DetailAsserts.
+     */
+    public static boolean detailedAssertionsEnabled(OptionValues values) {
+        return assertionsEnabled() && Options.DetailedAsserts.getValue(values);
+    }
+
+    // @formatter:off
+    public static class Options {
+
+        @Option(help = "Enable expensive assertions. (Require normal assertions enabled)", type = OptionType.Debug)
+        public static final OptionKey<Boolean> DetailedAsserts = new OptionKey<>(true);
+
+    }
+    // @formatter:on
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java	Thu Aug 24 09:44:52 2017 +0200
@@ -65,7 +65,7 @@
                         DebugOptions.TrackMemUse.getValue(options),
                         DebugOptions.Time.getValue(options),
                         DebugOptions.Dump.getValue(options),
-                        DebugOptions.Verify.getValue(options),
+                        getVerifyOptionValue(options),
                         DebugOptions.MethodFilter.getValue(options),
                         output, dumpHandlers, verifyHandlers);
     }
@@ -99,6 +99,10 @@
         this.output = output;
     }
 
+    private static String getVerifyOptionValue(OptionValues values) {
+        return !DebugOptions.Verify.hasBeenSet(values) && Assertions.assertionsEnabled() ? "" : DebugOptions.Verify.getValue(values);
+    }
+
     @Override
     public OptionValues getOptions() {
         return options;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Thu Aug 24 09:44:52 2017 +0200
@@ -32,11 +32,9 @@
 import static org.graalvm.compiler.debug.DebugOptions.ListMetrics;
 import static org.graalvm.compiler.debug.DebugOptions.Log;
 import static org.graalvm.compiler.debug.DebugOptions.MemUseTrackers;
-import static org.graalvm.compiler.debug.DebugOptions.MethodFilter;
 import static org.graalvm.compiler.debug.DebugOptions.Time;
 import static org.graalvm.compiler.debug.DebugOptions.Timers;
 import static org.graalvm.compiler.debug.DebugOptions.TrackMemUse;
-import static org.graalvm.compiler.debug.DebugOptions.Verify;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -374,16 +372,7 @@
                     }
                 }
             }
-            currentConfig = new DebugConfigImpl(
-                            options,
-                            Log.getValue(options),
-                            Count.getValue(options),
-                            TrackMemUse.getValue(options),
-                            Time.getValue(options),
-                            Dump.getValue(options),
-                            Verify.getValue(options),
-                            MethodFilter.getValue(options),
-                            logStream, dumpHandlers, verifyHandlers);
+            currentConfig = new DebugConfigImpl(options, logStream, dumpHandlers, verifyHandlers);
             currentScope = new ScopeImpl(this, Thread.currentThread());
             currentScope.updateFlags(currentConfig);
             metricsEnabled = true;
@@ -575,7 +564,7 @@
         }
     }
 
-    private final Invariants invariants = Assertions.ENABLED ? new Invariants() : null;
+    private final Invariants invariants = Assertions.assertionsEnabled() ? new Invariants() : null;
 
     static StackTraceElement[] getStackTrace(Thread thread) {
         return thread.getStackTrace();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,11 +22,9 @@
  */
 package org.graalvm.compiler.debug;
 
-import com.sun.management.ThreadMXBean;
-
 /**
- * Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed
- * using the try-with-resources pattern:
+ * Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility
+ * should be employed using the try-with-resources pattern:
  *
  * <pre>
  * try (DebugMemUseTracker.Closeable a = memUseTracker.start()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java	Thu Aug 24 09:44:52 2017 +0200
@@ -75,7 +75,7 @@
     public static final OptionKey<String> Time = new OptionKey<>(null);
 
     @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug)
-    public static final OptionKey<String> Verify = new OptionKey<>(Assertions.ENABLED ? "" : null);
+    public static final OptionKey<String> Verify = new OptionKey<>(null);
     @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug)
     public static final OptionKey<String> Dump = new OptionKey<>(null);
     @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug)
@@ -115,7 +115,7 @@
     @Option(help = "The directory where various Graal dump files are written.")
     public static final OptionKey<String> DumpPath = new OptionKey<>("dumps");
     @Option(help = "Print the name of each dump file path as it's created.")
-    public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(Assertions.ENABLED);
+    public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(false);
 
     @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug)
     public static final OptionKey<Boolean> PrintCFG = new OptionKey<>(false);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,7 +25,6 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.lang.management.ManagementFactory;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -74,16 +73,20 @@
      * Gets a unique identifier for this execution such as a process ID.
      */
     protected String getExecutionID() {
-        String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
         try {
-            int index = runtimeName.indexOf('@');
-            if (index != -1) {
-                long pid = Long.parseLong(runtimeName.substring(0, index));
-                return Long.toString(pid);
+            String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
+            try {
+                int index = runtimeName.indexOf('@');
+                if (index != -1) {
+                    long pid = Long.parseLong(runtimeName.substring(0, index));
+                    return Long.toString(pid);
+                }
+            } catch (NumberFormatException e) {
             }
-        } catch (NumberFormatException e) {
+            return runtimeName;
+        } catch (LinkageError err) {
+            return String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
         }
-        return runtimeName;
     }
 
     private synchronized String getPath(boolean createIfNull) {
@@ -148,7 +151,8 @@
                         @Override
                         public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                             if (attrs.isRegularFile()) {
-                                ZipEntry ze = new ZipEntry(file.toString());
+                                String name = dir.relativize(file).toString();
+                                ZipEntry ze = new ZipEntry(name);
                                 zos.putNextEntry(ze);
                                 zos.write(Files.readAllBytes(file));
                                 zos.closeEntry();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java	Thu Aug 24 09:44:52 2017 +0200
@@ -24,12 +24,6 @@
 
 import static java.lang.Thread.currentThread;
 
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-
-import javax.management.ObjectName;
-
 public class Management {
 
     private static final com.sun.management.ThreadMXBean threadMXBean = Management.initThreadMXBean();
@@ -46,20 +40,20 @@
 
     private static com.sun.management.ThreadMXBean initThreadMXBean() {
         try {
-            return (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
+            return (com.sun.management.ThreadMXBean) java.lang.management.ManagementFactory.getThreadMXBean();
         } catch (Error err) {
             return new UnimplementedBean();
         }
     }
 
-    public static ThreadMXBean getThreadMXBean() {
+    public static java.lang.management.ThreadMXBean getThreadMXBean() {
         return threadMXBean;
     }
 
-    private static class UnimplementedBean implements ThreadMXBean, com.sun.management.ThreadMXBean {
+    private static class UnimplementedBean implements java.lang.management.ThreadMXBean, com.sun.management.ThreadMXBean {
 
         @Override
-        public ObjectName getObjectName() {
+        public javax.management.ObjectName getObjectName() {
             return null;
         }
 
@@ -123,22 +117,22 @@
         }
 
         @Override
-        public ThreadInfo getThreadInfo(long id) {
+        public java.lang.management.ThreadInfo getThreadInfo(long id) {
             return null;
         }
 
         @Override
-        public ThreadInfo[] getThreadInfo(long[] ids) {
+        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids) {
             return null;
         }
 
         @Override
-        public ThreadInfo getThreadInfo(long id, int maxDepth) {
+        public java.lang.management.ThreadInfo getThreadInfo(long id, int maxDepth) {
             return null;
         }
 
         @Override
-        public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
+        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
             return null;
         }
 
@@ -220,12 +214,12 @@
         }
 
         @Override
-        public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) {
+        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) {
             return null;
         }
 
         @Override
-        public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
+        public java.lang.management.ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
             return null;
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,11 +22,9 @@
  */
 package org.graalvm.compiler.debug;
 
-import com.sun.management.ThreadMXBean;
-
 /**
- * Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed
- * using the try-with-resources pattern:
+ * Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility
+ * should be employed using the try-with-resources pattern:
  *
  * <pre>
  * try (DebugCloseable a = memUseTracker.start()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,14 +22,12 @@
  */
 package org.graalvm.compiler.debug;
 
-import java.lang.management.ThreadMXBean;
-
 /**
  * A consistent source of timing data that should be used by all facilities in the debug package.
  */
 public class TimeSource {
     private static final boolean USING_BEAN;
-    private static final ThreadMXBean threadMXBean;
+    private static final java.lang.management.ThreadMXBean threadMXBean;
 
     static {
         threadMXBean = Management.getThreadMXBean();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -119,7 +119,7 @@
         TestNode newNode = graph.add(new TestNode());
         try {
             map.get(newNode);
-            fail("expected " + (Assertions.ENABLED ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName()));
+            fail("expected " + (Assertions.assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName()));
         } catch (AssertionError ae) {
             // thrown when assertions are enabled
         } catch (ArrayIndexOutOfBoundsException e) {
@@ -136,7 +136,7 @@
         TestNode newNode = graph.add(new TestNode());
         try {
             map.set(newNode, 1);
-            fail("expected " + (Assertions.ENABLED ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName()));
+            fail("expected " + (Assertions.assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName()));
         } catch (AssertionError ae) {
             // thrown when assertions are enabled
         } catch (ArrayIndexOutOfBoundsException e) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java	Thu Aug 24 09:44:52 2017 +0200
@@ -31,9 +31,11 @@
 import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
 import org.graalvm.compiler.phases.common.ExpandLogicPhase;
 import org.graalvm.compiler.phases.common.FixReadsPhase;
+import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
 import org.graalvm.compiler.phases.tiers.LowTierContext;
 import org.graalvm.compiler.phases.tiers.Suites;
 import org.graalvm.compiler.phases.tiers.SuitesCreator;
+import org.graalvm.compiler.replacements.aarch64.AArch64ReadReplacementPhase;
 
 import java.util.ListIterator;
 
@@ -60,6 +62,9 @@
         }
         findPhase.add(new AddressLoweringByUsePhase(addressLoweringByUse));
 
+        findPhase = suites.getLowTier().findPhase(PropagateDeoptimizeProbabilityPhase.class);
+        findPhase.add(new AArch64ReadReplacementPhase());
+
         return suites;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java	Thu Aug 24 09:44:52 2017 +0200
@@ -23,7 +23,7 @@
 package org.graalvm.compiler.hotspot.amd64;
 
 import org.graalvm.compiler.core.amd64.AMD64SuitesCreator;
-import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.hotspot.lir.HotSpotZapRegistersPhase;
 import org.graalvm.compiler.lir.phases.LIRSuites;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
@@ -39,7 +39,7 @@
     @Override
     public LIRSuites createLIRSuites(OptionValues options) {
         LIRSuites lirSuites = super.createLIRSuites(options);
-        if (GraalOptions.DetailedAsserts.getValue(options)) {
+        if (Assertions.detailedAssertionsEnabled(options)) {
             lirSuites.getPostAllocationOptimizationStage().appendPhase(new HotSpotZapRegistersPhase());
         }
         return lirSuites;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Thu Aug 24 09:44:52 2017 +0200
@@ -88,7 +88,19 @@
     }
 
     public static ResolvedJavaMethod resolveIntrinsic(MetaAccessProvider metaAccess, VMIntrinsicMethod intrinsic) throws ClassNotFoundException {
-        Class<?> c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader());
+        Class<?> c;
+        try {
+            c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader());
+        } catch (ClassNotFoundException ex) {
+            try {
+                Class.forName("javax.naming.Reference");
+            } catch (ClassNotFoundException coreNamingMissing) {
+                // if core JDK classes aren't found, we are probably running in a
+                // JDK9 java.base environment and then missing class is OK
+                return null;
+            }
+            throw ex;
+        }
         for (Method javaMethod : c.getDeclaredMethods()) {
             if (javaMethod.getName().equals(intrinsic.name)) {
                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(javaMethod);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -29,28 +29,38 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.graalvm.compiler.core.GraalCompilerOptions;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.test.SubprocessUtil;
 import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 
 /**
  * Tests support for dumping graphs and other info useful for debugging a compiler crash.
  */
 public class CompilationWrapperTest extends GraalCompilerTest {
+    public CompilationWrapperTest() {
+        try {
+            Class.forName("java.lang.management.ManagementFactory");
+        } catch (ClassNotFoundException ex) {
+            Assume.assumeNoException("skip this test if there is no java.management JDK9 module around", ex);
+        }
+    }
 
     /**
      * Tests compilation requested by the VM.
      */
     @Test
     public void testVMCompilation1() throws IOException, InterruptedException {
-        testHelper(Arrays.asList("-XX:+BootstrapJVMCI",
+        testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI",
                         "-XX:+UseJVMCICompiler",
                         "-Dgraal.CompilationFailureAction=ExitVM",
                         "-Dgraal.CrashAt=Object.*,String.*",
@@ -63,66 +73,120 @@
      */
     @Test
     public void testVMCompilation2() throws IOException, InterruptedException {
-        testHelper(Arrays.asList("-XX:+BootstrapJVMCI",
+        testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI",
                         "-XX:+UseJVMCICompiler",
                         "-Dgraal.ExitVMOnException=true",
                         "-Dgraal.CrashAt=Object.*,String.*",
                         "-version"));
     }
 
+    static class Probe {
+        final String substring;
+        final int expectedOccurrences;
+        int actualOccurrences;
+        String lastMatchingLine;
+
+        Probe(String substring, int expectedOccurrences) {
+            this.substring = substring;
+            this.expectedOccurrences = expectedOccurrences;
+        }
+
+        boolean matches(String line) {
+            if (line.contains(substring)) {
+                actualOccurrences++;
+                lastMatchingLine = line;
+                return true;
+            }
+            return false;
+        }
+
+        String test() {
+            return expectedOccurrences == actualOccurrences ? null : String.format("expected %d, got %d occurrences", expectedOccurrences, actualOccurrences);
+        }
+    }
+
+    /**
+     * Tests {@link GraalCompilerOptions#MaxCompilationProblemsPerAction} in context of a
+     * compilation requested by the VM.
+     */
+    @Test
+    public void testVMCompilation3() throws IOException, InterruptedException {
+        final int maxProblems = 4;
+        Probe[] probes = {
+                        new Probe("To capture more information for diagnosing or reporting a compilation", maxProblems),
+                        new Probe("Retrying compilation of", maxProblems),
+                        new Probe("adjusting CompilationFailureAction from Diagnose to Print", 1),
+                        new Probe("adjusting CompilationFailureAction from Print to Silent", 1),
+        };
+        testHelper(Arrays.asList(probes), Arrays.asList("-XX:+BootstrapJVMCI",
+                        "-XX:+UseJVMCICompiler",
+                        "-Dgraal.CompilationFailureAction=Diagnose",
+                        "-Dgraal.MaxCompilationProblemsPerAction=" + maxProblems,
+                        "-Dgraal.CrashAt=Object.*,String.*",
+                        "-version"));
+    }
+
     /**
      * Tests compilation requested by Truffle.
      */
     @Test
     public void testTruffleCompilation() throws IOException, InterruptedException {
-        testHelper(Arrays.asList(
-                        "-Dgraal.CompilationFailureAction=ExitVM",
-                        "-Dgraal.CrashAt=root test1"),
-                        "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite",
-                        "test");
+        testHelper(Collections.emptyList(),
+                        Arrays.asList(
+                                        "-Dgraal.CompilationFailureAction=ExitVM",
+                                        "-Dgraal.CrashAt=root test1"),
+                        "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
     }
 
-    private static void testHelper(List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
+    private static final boolean VERBOSE = Boolean.getBoolean(CompilationWrapperTest.class.getSimpleName() + ".verbose");
+
+    private static void testHelper(List<Probe> initialProbes, List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
         final File dumpPath = new File(CompilationWrapperTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile();
         List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
         vmArgs.removeIf(a -> a.startsWith("-Dgraal."));
+        vmArgs.remove("-esa");
+        vmArgs.remove("-ea");
         vmArgs.add("-Dgraal.DumpPath=" + dumpPath);
         // Force output to a file even if there's a running IGV instance available.
         vmArgs.add("-Dgraal.PrintGraphFile=true");
         vmArgs.addAll(extraVmArgs);
 
         Subprocess proc = SubprocessUtil.java(vmArgs, mainClassAndArgs);
-        System.out.println(proc);
+        if (VERBOSE) {
+            System.out.println(proc);
+        }
 
-        String forcedCrashString = "Forced crash after compiling";
-        String diagnosticOutputFilePrefix = "Graal diagnostic output saved in ";
-
-        boolean seenForcedCrashString = false;
-        String diagnosticOutputZip = null;
+        List<Probe> probes = new ArrayList<>(initialProbes);
+        Probe diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1);
+        probes.add(diagnosticProbe);
+        probes.add(new Probe("Forced crash after compiling", Integer.MAX_VALUE) {
+            @Override
+            String test() {
+                return actualOccurrences > 0 ? null : "expected at least 1 occurrence";
+            }
+        });
 
         for (String line : proc.output) {
-            if (line.contains(forcedCrashString)) {
-                seenForcedCrashString = true;
-            } else if (diagnosticOutputZip == null) {
-                int index = line.indexOf(diagnosticOutputFilePrefix);
-                if (index != -1) {
-                    diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim();
+            for (Probe probe : probes) {
+                if (probe.matches(line)) {
+                    break;
                 }
             }
         }
-
-        if (!seenForcedCrashString) {
-            Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, proc));
-        }
-        if (diagnosticOutputZip == null) {
-            Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, proc));
+        for (Probe probe : probes) {
+            String error = probe.test();
+            if (error != null) {
+                Assert.fail(String.format("Did not find expected occurences of '%s' in output of command: %s%n%s", probe.substring, error, proc));
+            }
         }
 
-        String[] dumpPathEntries = dumpPath.list();
+        String diagnosticOutputZip = diagnosticProbe.lastMatchingLine.substring(diagnosticProbe.substring.length()).trim();
+
+        List<String> dumpPathEntries = Arrays.asList(dumpPath.list());
 
         File zip = new File(diagnosticOutputZip).getAbsoluteFile();
         Assert.assertTrue(zip.toString(), zip.exists());
-        Assert.assertArrayEquals(dumpPathEntries, new String[]{zip.getName()});
+        Assert.assertTrue(zip + " not in " + dumpPathEntries, dumpPathEntries.contains(zip.getName()));
         try {
             int bgv = 0;
             int cfg = 0;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -43,6 +43,7 @@
 import org.junit.Test;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.junit.Assume;
 
 /**
  * Test on-stack-replacement with locks.
@@ -51,6 +52,14 @@
 
     private static boolean TestInSeparateThread = false;
 
+    public GraalOSRLockTest() {
+        try {
+            Class.forName("java.lang.management.ManagementFactory");
+        } catch (ClassNotFoundException ex) {
+            Assume.assumeNoException("cannot check for monitors without java.management JDK9 module", ex);
+        }
+    }
+
     // testing only
     public static boolean isMonitorLockHeld(Object o) {
         return isMonitorLockHeldByThread(o, null);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -110,7 +110,7 @@
         MBeanInfo info = server.getMBeanInfo(name);
         assertNotNull("Info is found", info);
 
-        MBeanAttributeInfo printCompilation = findAttributeInfo("PrintCompilation", info);
+        MBeanAttributeInfo printCompilation = (MBeanAttributeInfo) findAttributeInfo("PrintCompilation", info);
         assertNotNull("PrintCompilation found", printCompilation);
         assertEquals("true/false", Boolean.class.getName(), printCompilation.getType());
 
@@ -124,9 +124,9 @@
         assertEquals("Changed to on", Boolean.TRUE, after);
     }
 
-    private static MBeanAttributeInfo findAttributeInfo(String attrName, MBeanInfo info) {
+    private static Object findAttributeInfo(String attrName, Object info) {
         MBeanAttributeInfo printCompilation = null;
-        for (MBeanAttributeInfo attr : info.getAttributes()) {
+        for (MBeanAttributeInfo attr : ((MBeanInfo) info).getAttributes()) {
             if (attr.getName().equals(attrName)) {
                 assertTrue("Readable", attr.isReadable());
                 assertTrue("Writable", attr.isWritable());
@@ -157,7 +157,7 @@
         MBeanInfo info = server.getMBeanInfo(name);
         assertNotNull("Info is found", info);
 
-        MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
+        MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
 
         Attribute dumpTo1 = new Attribute(dump.getName(), 1);
 
@@ -215,7 +215,7 @@
                         "java.util.Arrays", "asList", ":3"
         }, null);
 
-        MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
+        MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
         Attribute dumpTo1 = new Attribute(dump.getName(), "");
         server.setAttribute(name, dumpTo1);
         Object after = server.getAttribute(name, dump.getName());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java	Thu Aug 24 09:44:52 2017 +0200
@@ -46,7 +46,6 @@
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
-import com.sun.management.ThreadMXBean;
 
 import jdk.vm.ci.hotspot.HotSpotInstalledCode;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -88,7 +87,7 @@
     private static long zeroTime = System.nanoTime();
 
     private static long getThreadAllocatedBytes() {
-        ThreadMXBean thread = (ThreadMXBean) Management.getThreadMXBean();
+        com.sun.management.ThreadMXBean thread = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
         return thread.getThreadAllocatedBytes(currentThread().getId());
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Thu Aug 24 09:44:52 2017 +0200
@@ -53,6 +53,7 @@
 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
 import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult;
 import jdk.vm.ci.hotspot.HotSpotInstalledCode;
+import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
 import jdk.vm.ci.hotspot.HotSpotNmethod;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -95,7 +96,7 @@
         CompilationResult result;
 
         HotSpotCompilationWrapper(EventProvider.CompilationEvent compilationEvent) {
-            super(compiler.getGraalRuntime().getOutputDirectory());
+            super(compiler.getGraalRuntime().getOutputDirectory(), compiler.getGraalRuntime().getCompilationProblemsPerAction());
             this.compilationEvent = compilationEvent;
         }
 
@@ -145,7 +146,7 @@
              * respect CompilationFailureAction if it has been explicitly set.
              */
             if (actionKey == CompilationFailureAction && !actionKey.hasBeenSet(values)) {
-                if (Assertions.ENABLED || compiler.getGraalRuntime().isBootstrapping()) {
+                if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
                     return ExitVM;
                 }
             }
@@ -305,6 +306,10 @@
             if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) {
                 return HotSpotCompilationRequestResult.failure("Already compiled", false);
             }
+            if (HotSpotGraalCompilerFactory.checkGraalCompileOnlyFilter(method.getDeclaringClass().toJavaName(), method.getName(), method.getSignature().toString(),
+                            HotSpotJVMCICompilerFactory.CompilationLevel.FullOptimization) != HotSpotJVMCICompilerFactory.CompilationLevel.FullOptimization) {
+                return HotSpotCompilationRequestResult.failure("GraalCompileOnly excluded", false);
+            }
         }
 
         HotSpotCompilationWrapper compilation = new HotSpotCompilationWrapper(compilationEvent);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Thu Aug 24 09:44:52 2017 +0200
@@ -130,7 +130,7 @@
      * List used to assert uniqueness of {@link #name} and {@link #autoSelectionPriority} across all
      * {@link CompilerConfigurationFactory} instances.
      */
-    private static final List<CompilerConfigurationFactory> factories = Assertions.ENABLED ? new ArrayList<>() : null;
+    private static final List<CompilerConfigurationFactory> factories = Assertions.assertionsEnabled() ? new ArrayList<>() : null;
 
     private static boolean checkAndAddNewFactory(CompilerConfigurationFactory factory) {
         for (CompilerConfigurationFactory other : factories) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Thu Aug 24 09:44:52 2017 +0200
@@ -146,7 +146,7 @@
         }
     }
 
-    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
+    public StructuredGraph createGraph(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
         HotSpotBackend backend = graalRuntime.getHostBackend();
         HotSpotProviders providers = backend.getProviders();
         final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
@@ -160,6 +160,15 @@
             graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog(
                             speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build();
         }
+        return graph;
+    }
+
+    public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo,
+                    OptionValues options) {
+
+        HotSpotBackend backend = graalRuntime.getHostBackend();
+        HotSpotProviders providers = backend.getProviders();
+        final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
 
         Suites suites = getSuites(providers, options);
         LIRSuites lirSuites = getLIRSuites(providers, options);
@@ -173,11 +182,11 @@
         if (isOSR && !OnStackReplacementPhase.Options.DeoptAfterOSR.getValue(options)) {
             optimisticOpts.remove(Optimization.RemoveNeverExecutedCode);
         }
-        CompilationResult result = new CompilationResult();
+
         result.setEntryBCI(entryBCI);
         boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints();
         PhaseSuite<HighTierContext> graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR);
-        GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, CompilationResultBuilderFactory.Default);
+        GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, crbf);
 
         if (!isOSR && useProfilingInfo) {
             ProfilingInfo profile = profilingInfo;
@@ -187,6 +196,12 @@
         return result;
     }
 
+    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
+        StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug);
+        CompilationResult result = new CompilationResult();
+        return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options);
+    }
+
     /**
      * Gets a graph produced from the intrinsic for a given method that can be compiled and
      * installed for the method.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Thu Aug 24 09:44:52 2017 +0200
@@ -162,9 +162,20 @@
      * This method is static so it can be exercised during initialization.
      */
     private static CompilationLevel adjustCompilationLevelInternal(Class<?> declaringClass, String name, String signature, CompilationLevel level) {
+        if (compileGraalWithC1Only) {
+            if (level.ordinal() > CompilationLevel.Simple.ordinal()) {
+                String declaringClassName = declaringClass.getName();
+                if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) {
+                    return CompilationLevel.Simple;
+                }
+            }
+        }
+        return checkGraalCompileOnlyFilter(declaringClass.getName(), name, signature, level);
+    }
+
+    public static CompilationLevel checkGraalCompileOnlyFilter(String declaringClassName, String name, String signature, CompilationLevel level) {
         if (graalCompileOnlyFilter != null) {
             if (level == CompilationLevel.FullOptimization) {
-                String declaringClassName = declaringClass.getName();
                 HotSpotSignature sig = null;
                 for (MethodFilter filter : graalCompileOnlyFilter) {
                     if (filter.hasSignature() && sig == null) {
@@ -177,14 +188,6 @@
                 return CompilationLevel.Simple;
             }
         }
-        if (compileGraalWithC1Only) {
-            if (level.ordinal() > CompilationLevel.Simple.ordinal()) {
-                String declaringClassName = declaringClass.getName();
-                if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) {
-                    return CompilationLevel.Simple;
-                }
-            }
-        }
         return level;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,7 +22,6 @@
  */
 package org.graalvm.compiler.hotspot;
 
-import java.lang.management.ManagementFactory;
 import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
@@ -30,22 +29,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
-import javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.DynamicMBean;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanParameterInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
@@ -66,14 +49,14 @@
 import org.graalvm.util.Equivalence;
 import org.graalvm.util.UnmodifiableEconomicMap;
 
-public final class HotSpotGraalMBean implements DynamicMBean {
+public final class HotSpotGraalMBean implements javax.management.DynamicMBean {
     private static Object mBeanServerField;
     private final HotSpotGraalCompiler compiler;
     private final OptionValues options;
     private final EconomicMap<OptionKey<?>, Object> changes;
     private final EconomicSet<Dump> methodDumps;
     private volatile EconomicSet<Reference<ClassLoader>> loaders;
-    private ObjectName registered;
+    private javax.management.ObjectName registered;
     private OptionValues cachedOptions;
 
     private HotSpotGraalMBean(HotSpotGraalCompiler compiler, OptionValues options) {
@@ -89,11 +72,11 @@
     private static boolean isMXServerOn() {
         if (mBeanServerField == null) {
             try {
-                final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer");
+                final Field field = java.lang.management.ManagementFactory.class.getDeclaredField("platformMBeanServer");
                 field.setAccessible(true);
                 mBeanServerField = field;
             } catch (Exception ex) {
-                mBeanServerField = ManagementFactory.class;
+                mBeanServerField = java.lang.management.ManagementFactory.class;
             }
         }
         if (mBeanServerField instanceof Field) {
@@ -113,7 +96,7 @@
         return mbean;
     }
 
-    public ObjectName ensureRegistered(boolean check) {
+    public javax.management.ObjectName ensureRegistered(boolean check) {
         for (int cnt = 0;; cnt++) {
             if (registered != null) {
                 return registered;
@@ -122,14 +105,14 @@
                 return null;
             }
             try {
-                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-                ObjectName name = new ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt));
+                javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer();
+                javax.management.ObjectName name = new javax.management.ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt));
                 mbs.registerMBean(this, name);
                 registered = name;
                 break;
-            } catch (MalformedObjectNameException | MBeanRegistrationException | NotCompliantMBeanException ex) {
+            } catch (javax.management.MalformedObjectNameException | javax.management.MBeanRegistrationException | javax.management.NotCompliantMBeanException ex) {
                 throw new IllegalStateException(ex);
-            } catch (InstanceAlreadyExistsException ex) {
+            } catch (javax.management.InstanceAlreadyExistsException ex) {
                 continue;
             }
         }
@@ -188,14 +171,14 @@
     }
 
     @Override
-    public void setAttribute(Attribute attribute) throws AttributeNotFoundException {
-        Attribute newAttr = setImpl(attribute);
+    public void setAttribute(javax.management.Attribute attribute) throws javax.management.AttributeNotFoundException {
+        javax.management.Attribute newAttr = setImpl(attribute);
         if (newAttr == null) {
-            throw new AttributeNotFoundException();
+            throw new javax.management.AttributeNotFoundException();
         }
     }
 
-    private Attribute setImpl(Attribute attribute) {
+    private javax.management.Attribute setImpl(javax.management.Attribute attribute) {
         cachedOptions = null;
         for (OptionDescriptor option : allOptionDescriptors()) {
             if (option.getName().equals(attribute.getName())) {
@@ -207,22 +190,22 @@
     }
 
     @Override
-    public AttributeList getAttributes(String[] names) {
-        AttributeList list = new AttributeList();
+    public javax.management.AttributeList getAttributes(String[] names) {
+        javax.management.AttributeList list = new javax.management.AttributeList();
         for (String name : names) {
             Object value = getAttribute(name);
             if (value != null) {
-                list.add(new Attribute(name, value));
+                list.add(new javax.management.Attribute(name, value));
             }
         }
         return list;
     }
 
     @Override
-    public AttributeList setAttributes(AttributeList attributes) {
-        AttributeList setOk = new AttributeList();
-        for (Attribute attr : attributes.asList()) {
-            Attribute newAttr = setImpl(attr);
+    public javax.management.AttributeList setAttributes(javax.management.AttributeList attributes) {
+        javax.management.AttributeList setOk = new javax.management.AttributeList();
+        for (javax.management.Attribute attr : attributes.asList()) {
+            javax.management.Attribute newAttr = setImpl(attr);
             if (newAttr != null) {
                 setOk.add(newAttr);
             }
@@ -231,7 +214,7 @@
     }
 
     @Override
-    public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
+    public Object invoke(String actionName, Object[] params, String[] signature) throws javax.management.MBeanException, javax.management.ReflectionException {
         if ("dumpMethod".equals(actionName)) {
             try {
                 String className = param(params, 0, "className", String.class, null);
@@ -241,7 +224,7 @@
                 Number port = param(params, 4, "port", Number.class, 4445);
                 dumpMethod(className, methodName, filter, host, port.intValue());
             } catch (Exception ex) {
-                throw new ReflectionException(ex);
+                throw new javax.management.ReflectionException(ex);
             }
         }
         return null;
@@ -261,7 +244,7 @@
         throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value);
     }
 
-    public void dumpMethod(String className, String methodName, String filter, String host, int port) throws MBeanException {
+    public void dumpMethod(String className, String methodName, String filter, String host, int port) throws javax.management.MBeanException {
         String jvmName = MetaUtil.toInternalName(className);
         methodDumps.add(new Dump(host, port, jvmName, methodName, filter));
 
@@ -293,41 +276,41 @@
             }
         }
         if (found.isEmpty()) {
-            throw new MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
+            throw new javax.management.MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
         }
     }
 
     @Override
-    public MBeanInfo getMBeanInfo() {
-        List<MBeanAttributeInfo> attrs = new ArrayList<>();
+    public javax.management.MBeanInfo getMBeanInfo() {
+        List<javax.management.MBeanAttributeInfo> attrs = new ArrayList<>();
         if (registered != null) {
             for (OptionDescriptor descr : allOptionDescriptors()) {
-                attrs.add(new MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
+                attrs.add(new javax.management.MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
             }
         }
-        MBeanOperationInfo[] ops = {
-                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
-                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                        }, "void", MBeanOperationInfo.ACTION),
-                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
-                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                                        new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
-                        }, "void", MBeanOperationInfo.ACTION),
-                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
-                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                                        new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
-                                        new MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
-                                        new MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
-                        }, "void", MBeanOperationInfo.ACTION)
+        javax.management.MBeanOperationInfo[] ops = {
+                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
+                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                        }, "void", javax.management.MBeanOperationInfo.ACTION),
+                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
+                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                                        new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+                        }, "void", javax.management.MBeanOperationInfo.ACTION),
+                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
+                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                                        new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+                                        new javax.management.MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
+                                        new javax.management.MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
+                        }, "void", javax.management.MBeanOperationInfo.ACTION)
         };
 
-        return new MBeanInfo(
+        return new javax.management.MBeanInfo(
                         HotSpotGraalMBean.class.getName(),
                         "Graal",
-                        attrs.toArray(new MBeanAttributeInfo[attrs.size()]),
+                        attrs.toArray(new javax.management.MBeanAttributeInfo[attrs.size()]),
                         null, ops, null);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Thu Aug 24 09:44:52 2017 +0200
@@ -30,10 +30,13 @@
 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
 
 import java.util.ArrayList;
+import java.util.EnumMap;
 import java.util.List;
+import java.util.Map;
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.api.runtime.GraalRuntime;
+import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.target.Backend;
@@ -95,6 +98,7 @@
 
     private final OptionValues options;
     private final DiagnosticsOutputDirectory outputDirectory;
+    private final Map<ExceptionAction, Integer> compilationProblemsPerAction;
     private final HotSpotGraalMBean mBean;
 
     /**
@@ -114,11 +118,12 @@
         }
 
         outputDirectory = new DiagnosticsOutputDirectory(options);
+        compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class);
         snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null;
         CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
 
         HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions);
-        this.mBean = HotSpotGraalMBean.create(compiler);
+        this.mBean = createHotSpotGraalMBean(compiler);
 
         BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
 
@@ -167,6 +172,14 @@
         bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
     }
 
+    private static HotSpotGraalMBean createHotSpotGraalMBean(HotSpotGraalCompiler compiler) {
+        try {
+            return HotSpotGraalMBean.create(compiler);
+        } catch (LinkageError ex) {
+            return null;
+        }
+    }
+
     private HotSpotBackend registerBackend(HotSpotBackend backend) {
         Class<? extends Architecture> arch = backend.getTarget().arch.getClass();
         HotSpotBackend oldValue = backends.put(arch, backend);
@@ -192,12 +205,12 @@
 
     @Override
     public OptionValues getOptions() {
-        return mBean.optionsFor(options, null);
+        return mBean == null ? options : mBean.optionsFor(options, null);
     }
 
     @Override
     public OptionValues getOptions(ResolvedJavaMethod forMethod) {
-        return mBean.optionsFor(options, forMethod);
+        return mBean == null ? options : mBean.optionsFor(options, forMethod);
     }
 
     @Override
@@ -298,4 +311,9 @@
     public DiagnosticsOutputDirectory getOutputDirectory() {
         return outputDirectory;
     }
+
+    @Override
+    public Map<ExceptionAction, Integer> getCompilationProblemsPerAction() {
+        return compilationProblemsPerAction;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,7 +22,10 @@
  */
 package org.graalvm.compiler.hotspot;
 
+import java.util.Map;
+
 import org.graalvm.compiler.api.runtime.GraalRuntime;
+import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
@@ -95,4 +98,9 @@
      * Gets a directory into which diagnostics such crash reports and dumps should be written.
      */
     DiagnosticsOutputDirectory getOutputDirectory();
+
+    /**
+     * Gets the map used to count compilation problems at each {@link ExceptionAction} level.
+     */
+    Map<ExceptionAction, Integer> getCompilationProblemsPerAction();
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java	Thu Aug 24 09:44:52 2017 +0200
@@ -27,7 +27,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
-import java.lang.management.ManagementFactory;
 
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
@@ -53,8 +52,8 @@
     private String getFilename(OptionValues options) {
         String name = getValue(options);
         if (name.contains("%p")) {
-            String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
             try {
+                String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
                 int index = runtimeName.indexOf('@');
                 if (index != -1) {
                     long pid = Long.parseLong(runtimeName.substring(0, index));
@@ -63,6 +62,8 @@
                 name = name.replaceAll("%p", runtimeName);
             } catch (NumberFormatException e) {
 
+            } catch (LinkageError err) {
+                name = String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
             }
         }
         if (name.contains("%t")) {
@@ -124,7 +125,7 @@
                 /*
                  * Add the JVM and Java arguments to the log file to help identity it.
                  */
-                String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments());
+                String inputArguments = String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
                 ps.println("VM Arguments: " + inputArguments);
                 String cmd = System.getProperty("sun.java.command");
                 if (cmd != null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java	Thu Aug 24 09:44:52 2017 +0200
@@ -153,7 +153,7 @@
     @Fold
     @SuppressWarnings("all")
     static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) {
-        return Assertions.ENABLED || cAssertionsEnabled(config);
+        return Assertions.assertionsEnabled() || cAssertionsEnabled(config);
     }
 
     public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = newDescriptor(ExceptionHandlerStub.class, "exceptionHandlerForPc", Word.class, Word.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java	Thu Aug 24 09:44:52 2017 +0200
@@ -116,7 +116,7 @@
     @Fold
     @SuppressWarnings("all")
     static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) {
-        return Assertions.ENABLED || cAssertionsEnabled(config);
+        return Assertions.assertionsEnabled() || cAssertionsEnabled(config);
     }
 
     public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Thu Aug 24 09:44:52 2017 +0200
@@ -371,6 +371,7 @@
 import org.graalvm.compiler.nodes.extended.LoadHubNode;
 import org.graalvm.compiler.nodes.extended.LoadMethodNode;
 import org.graalvm.compiler.nodes.extended.MembarNode;
+import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
 import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
 import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
@@ -509,6 +510,8 @@
          */
         private void processPlaceholderFrameStates(IntrinsicContext intrinsic) {
             StructuredGraph graph = parser.getGraph();
+            graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before processPlaceholderFrameStates in %s", parser.method);
+            boolean sawInvalidFrameState = false;
             for (Node node : graph.getNewNodes(mark)) {
                 if (node instanceof FrameState) {
                     FrameState frameState = (FrameState) node;
@@ -546,6 +549,7 @@
                                     FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
                                     newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
                                     frameState.replaceAndDelete(newFrameState);
+                                    sawInvalidFrameState = true;
                                 } else {
                                     // An intrinsic for a void method.
                                     FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), null);
@@ -584,6 +588,17 @@
                     }
                 }
             }
+            if (sawInvalidFrameState) {
+                JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
+                FrameStateBuilder frameStateBuilder = parser.frameState;
+                ValueNode returnValue = frameStateBuilder.pop(returnKind);
+                StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue));
+                parser.lastInstr.setNext(proxy);
+                frameStateBuilder.push(returnKind, proxy);
+                proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy));
+                parser.lastInstr = proxy;
+            }
+            graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method);
         }
     }
 
@@ -1236,6 +1251,10 @@
         }
     }
 
+    protected StateSplitProxyNode genVolatileFieldReadProxy(ValueNode fieldRead) {
+        return new StateSplitProxyNode(fieldRead);
+    }
+
     protected ValueNode emitExplicitNullCheck(ValueNode receiver) {
         if (StampTool.isPointerNonNull(receiver.stamp())) {
             return receiver;
@@ -1429,7 +1448,7 @@
         createNonInlinedInvoke(withExceptionEdge, bci(), callTarget, resultType);
     }
 
-    private Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
+    protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
         ResolvedJavaMethod targetMethod = initialTargetMethod;
         InvokeKind invokeKind = initialInvokeKind;
         if (initialInvokeKind.isIndirect()) {
@@ -1676,7 +1695,7 @@
         final Mark mark;
 
         InvocationPluginAssertions(InvocationPlugin plugin, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) {
-            guarantee(Assertions.ENABLED, "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName());
+            guarantee(Assertions.assertionsEnabled(), "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName());
             this.plugin = plugin;
             this.targetMethod = targetMethod;
             this.args = args;
@@ -1908,7 +1927,7 @@
                 }
             }
 
-            InvocationPluginAssertions assertions = Assertions.ENABLED ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
+            InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
             if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
                 afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
                 return true;
@@ -1982,7 +2001,7 @@
      */
     private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targetMethod) {
         byte[] bytecode = targetMethod.getCode();
-        if (bytecode.length == ACCESSOR_BYTECODE_LENGTH &&
+        if (bytecode != null && bytecode.length == ACCESSOR_BYTECODE_LENGTH &&
                         Bytes.beU1(bytecode, 0) == ALOAD_0 &&
                         Bytes.beU1(bytecode, 1) == GETFIELD) {
             int b4 = Bytes.beU1(bytecode, 4);
@@ -2183,6 +2202,14 @@
                     lastInstr = finishInstruction(returnMergeNode, frameState);
                 }
             }
+            /*
+             * Propagate any side effects into the caller when parsing intrinsics.
+             */
+            if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
+                for (StateSplit sideEffect : parser.frameState.sideEffects()) {
+                    frameState.addSideEffect(sideEffect);
+                }
+            }
 
             FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
             if (calleeBeforeUnwindNode != null) {
@@ -3032,7 +3059,7 @@
         ConstantNode falseValue = graph.unique(ConstantNode.forInt(falseBlockInt));
         ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue);
         if (conditionalNode.graph() == null) {
-            conditionalNode = graph.addOrUnique(conditionalNode);
+            conditionalNode = graph.addOrUniqueWithInputs(conditionalNode);
         }
         if (genReturn) {
             JavaKind returnKind = method.getSignature().getReturnKind().getStackKind();
@@ -3788,11 +3815,22 @@
             }
         }
 
-        frameState.push(resolvedField.getJavaKind(), append(genLoadField(receiver, resolvedField)));
+        ValueNode fieldRead = append(genLoadField(receiver, resolvedField));
+
         if (resolvedField.getDeclaringClass().getName().equals("Ljava/lang/ref/Reference;") && resolvedField.getName().equals("referent")) {
             LocationIdentity referentIdentity = new FieldLocationIdentity(resolvedField);
             append(new MembarNode(0, referentIdentity));
         }
+
+        JavaKind fieldKind = resolvedField.getJavaKind();
+
+        if (resolvedField.isVolatile() && fieldRead instanceof LoadFieldNode) {
+            StateSplitProxyNode readProxy = append(genVolatileFieldReadProxy(fieldRead));
+            frameState.push(fieldKind, readProxy);
+            readProxy.setStateAfter(frameState.create(stream.nextBCI(), readProxy));
+        } else {
+            frameState.push(fieldKind, fieldRead);
+        }
     }
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Thu Aug 24 09:44:52 2017 +0200
@@ -102,6 +102,7 @@
     private final StructuredGraph graph;
     private final boolean clearNonLiveLocals;
     private FrameState outerFrameState;
+    private NodeSourcePosition outerSourcePosition;
 
     /**
      * The closest {@link StateSplit#hasSideEffect() side-effect} predecessors. There will be more
@@ -364,13 +365,12 @@
             // Skip intrinsic frames
             parent = parser.getNonIntrinsicAncestor();
         }
-        return create(null, constantReceiver, bci, parent, hideSubstitutionStates);
+        return create(constantReceiver, bci, parent, hideSubstitutionStates);
     }
 
-    private NodeSourcePosition create(NodeSourcePosition o, JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) {
-        NodeSourcePosition outer = o;
-        if (outer == null && parent != null) {
-            outer = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates);
+    private NodeSourcePosition create(JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) {
+        if (outerSourcePosition == null && parent != null) {
+            outerSourcePosition = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates);
         }
         if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) {
             return FrameState.toSourcePosition(outerFrameState);
@@ -378,7 +378,7 @@
         if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
             throw shouldNotReachHere();
         }
-        return new NodeSourcePosition(receiver, outer, code.getMethod(), bci);
+        return new NodeSourcePosition(receiver, outerSourcePosition, code.getMethod(), bci);
     }
 
     public FrameStateBuilder copy() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/NotOnDebug.java	Thu Aug 24 09:44:52 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.jtt.hotspot;
+
+import org.junit.rules.DisableOnDebug;
+import org.junit.rules.TestRule;
+import org.junit.rules.Timeout;
+
+public final class NotOnDebug {
+    public static TestRule create(Timeout seconds) {
+        try {
+            return new DisableOnDebug(seconds);
+        } catch (LinkageError ex) {
+            return null;
+        }
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,13 +25,12 @@
 import org.graalvm.compiler.jtt.JTTTest;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Test6959129 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static long test() {
         int min = Integer.MAX_VALUE - 30000;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Monitor_contended01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         boolean started = false;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Monitor_notowner01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     static Object monitor = new Object();
     static Object finished = new Object();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Monitorenter01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     static final Object object = new Object();
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Monitorenter02 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     static final Object object = new Object();
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Object_wait01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Object_wait02 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java	Thu Aug 24 09:44:52 2017 +0200
@@ -30,11 +30,11 @@
 import org.graalvm.compiler.nodes.Cancellable;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 
 public class Object_wait03 extends JTTTest {
 
@@ -48,7 +48,7 @@
      */
     static final long TIMEOUT_MS = COMPILATION_TIMEOUT_MS * 2;
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.millis(TIMEOUT_MS));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.millis(TIMEOUT_MS));
 
     private static class TestClass implements Runnable {
         @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Object_wait04 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,9 +25,9 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
@@ -39,7 +39,7 @@
  */
 public final class SynchronizedLoopExit01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     protected Object object = new Object();
     protected volatile boolean drained = false;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java	Thu Aug 24 09:44:52 2017 +0200
@@ -27,17 +27,17 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 //Test all, mainly monitors
 public class Thread_isInterrupted02 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static final Object start = new Object();
     private static final Object end = new Object();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java	Thu Aug 24 09:44:52 2017 +0200
@@ -23,9 +23,9 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
@@ -35,7 +35,7 @@
 // Interrupted while sleeping, throws an interrupted exception
 public class Thread_isInterrupted03 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static boolean test() throws InterruptedException {
         final Thread1 thread = new Thread1();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java	Thu Aug 24 09:44:52 2017 +0200
@@ -23,9 +23,9 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
@@ -35,7 +35,7 @@
 // Interrupted during wait, with interrupter joining
 public class Thread_isInterrupted05 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static boolean test() throws InterruptedException {
         final WaitInterruptee waitInterruptee = new WaitInterruptee();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Thread_join01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java	Thu Aug 24 09:44:52 2017 +0200
@@ -28,15 +28,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Thread_join02 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java	Thu Aug 24 09:44:52 2017 +0200
@@ -28,15 +28,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Thread_join03 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Thread_sleep01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static boolean test(int i) throws InterruptedException {
         final long before = System.currentTimeMillis();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java	Thu Aug 24 09:44:52 2017 +0200
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Thread_yield01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static boolean test() {
         Thread.yield();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java	Thu Aug 24 09:44:52 2017 +0200
@@ -110,6 +110,8 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            boolean isNegated = false;
+            int jccPos = masm.position();
             /*
              * The strategy for emitting jumps is: If either trueDestination or falseDestination is
              * the successor block, assume the block scheduler did the correct thing and jcc to the
@@ -120,15 +122,18 @@
              */
             if (crb.isSuccessorEdge(trueDestination)) {
                 jcc(masm, true, falseDestination);
+                isNegated = true;
             } else if (crb.isSuccessorEdge(falseDestination)) {
                 jcc(masm, false, trueDestination);
             } else if (trueDestinationProbability < 0.5) {
                 jcc(masm, true, falseDestination);
                 masm.jmp(trueDestination.label());
+                isNegated = true;
             } else {
                 jcc(masm, false, trueDestination);
                 masm.jmp(falseDestination.label());
             }
+            crb.recordBranch(jccPos, isNegated);
         }
 
         protected void jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/Interval.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/Interval.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,7 +22,6 @@
  */
 package org.graalvm.compiler.lir.alloc.lsra;
 
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
@@ -39,6 +38,7 @@
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.util.IntList;
 import org.graalvm.compiler.core.common.util.Util;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.Variable;
@@ -1140,7 +1140,7 @@
         // split list of use positions
         result.usePosList = usePosList.splitAt(splitPos);
 
-        if (DetailedAsserts.getValue(allocator.getOptions())) {
+        if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) {
             for (int i = 0; i < usePosList.size(); i++) {
                 assert usePosList.usePos(i) < splitPos;
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java	Thu Aug 24 09:44:52 2017 +0200
@@ -27,7 +27,6 @@
 import static jdk.vm.ci.code.ValueUtil.isIllegal;
 import static jdk.vm.ci.code.ValueUtil.isLegal;
 import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
 import static org.graalvm.compiler.lir.phases.LIRPhase.Options.LIROptimization;
 
@@ -40,6 +39,7 @@
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.Indent;
@@ -206,7 +206,7 @@
         this.rangeEndMarker = new Range(Integer.MAX_VALUE, Integer.MAX_VALUE, null);
         this.intervalEndMarker = new Interval(Value.ILLEGAL, Interval.END_MARKER_OPERAND_NUMBER, null, rangeEndMarker);
         this.intervalEndMarker.next = intervalEndMarker;
-        this.detailedAsserts = DetailedAsserts.getValue(ir.getOptions());
+        this.detailedAsserts = Assertions.detailedAssertionsEnabled(ir.getOptions());
     }
 
     public LIRGenerationResult getLIRGenerationResult() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java	Thu Aug 24 09:44:52 2017 +0200
@@ -23,7 +23,6 @@
 package org.graalvm.compiler.lir.alloc.lsra;
 
 import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
 import static org.graalvm.compiler.lir.phases.LIRPhase.Options.LIROptimization;
@@ -31,6 +30,7 @@
 import java.util.ArrayList;
 
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.Indent;
 import org.graalvm.compiler.lir.LIRInsertionBuffer;
@@ -99,7 +99,7 @@
              */
             Interval interval;
             interval = allocator.createUnhandledLists(mustStoreAtDefinition, null).getLeft();
-            if (DetailedAsserts.getValue(allocator.getOptions())) {
+            if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) {
                 checkIntervals(debug, interval);
             }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java	Thu Aug 24 09:44:52 2017 +0200
@@ -26,7 +26,6 @@
 import static jdk.vm.ci.code.ValueUtil.asStackSlot;
 import static jdk.vm.ci.code.ValueUtil.isRegister;
 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.asVariable;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
 import static org.graalvm.compiler.lir.debug.LIRGenerationDebugContext.getSourceForOperandFromDebugContext;
@@ -41,6 +40,7 @@
 import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.core.common.util.BitMap2D;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.Indent;
@@ -88,7 +88,7 @@
         debug.dump(DebugContext.VERBOSE_LEVEL, lirGenRes.getLIR(), "Before register allocation");
         computeLocalLiveSets();
         computeGlobalLiveSets();
-        buildIntervals(DetailedAsserts.getValue(allocator.getOptions()));
+        buildIntervals(Assertions.detailedAssertionsEnabled(allocator.getOptions()));
     }
 
     /**
@@ -364,14 +364,14 @@
                 }
             } while (changeOccurred);
 
-            if (DetailedAsserts.getValue(allocator.getOptions())) {
+            if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) {
                 verifyLiveness();
             }
 
             // check that the liveIn set of the first block is empty
             AbstractBlockBase<?> startBlock = allocator.getLIR().getControlFlowGraph().getStartBlock();
             if (allocator.getBlockData(startBlock).liveIn.cardinality() != 0) {
-                if (DetailedAsserts.getValue(allocator.getOptions())) {
+                if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) {
                     reportFailure(numBlocks);
                 }
                 // bailout if this occurs in product mode.
@@ -570,7 +570,7 @@
             ValueMoveOp move = ValueMoveOp.asValueMoveOp(op);
             if (optimizeMethodArgument(move.getInput())) {
                 StackSlot slot = asStackSlot(move.getInput());
-                if (DetailedAsserts.getValue(allocator.getOptions())) {
+                if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) {
                     assert op.id() > 0 : "invalid id";
                     assert allocator.blockForId(op.id()).getPredecessorCount() == 0 : "move from stack must be in first block";
                     assert isVariable(move.getResult()) : "result of move must be a variable";
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java	Thu Aug 24 09:44:52 2017 +0200
@@ -26,7 +26,6 @@
 import static jdk.vm.ci.code.ValueUtil.asRegister;
 import static jdk.vm.ci.code.ValueUtil.isIllegal;
 import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.asVariable;
 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
@@ -42,6 +41,7 @@
 import org.graalvm.compiler.core.common.alloc.Trace;
 import org.graalvm.compiler.core.common.alloc.TraceBuilderResult;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.Indent;
 import org.graalvm.compiler.lir.InstructionValueProcedure;
@@ -224,7 +224,7 @@
                 debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId());
             }
 
-            if (DetailedAsserts.getValue(getLIR().getOptions())) {
+            if (Assertions.detailedAssertionsEnabled(getLIR().getOptions())) {
                 assert lir.getLIRforBlock(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label";
 
                 /*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceInterval.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceInterval.java	Thu Aug 24 09:44:52 2017 +0200
@@ -26,7 +26,6 @@
 import static jdk.vm.ci.code.ValueUtil.isIllegal;
 import static jdk.vm.ci.code.ValueUtil.isRegister;
 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
@@ -39,6 +38,7 @@
 
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.util.Util;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.Variable;
@@ -722,7 +722,7 @@
 
         // do not add use positions for precolored intervals because they are never used
         if (registerPriority != RegisterPriority.None) {
-            if (DetailedAsserts.getValue(options)) {
+            if (Assertions.detailedAssertionsEnabled(options)) {
                 for (int i = 0; i < numUsePos(); i++) {
                     assert pos <= getUsePos(i) : "already added a use-position with lower position";
                     if (i > 0) {
@@ -802,7 +802,7 @@
         // split list of use positions
         splitUsePosAt(result, splitPos);
 
-        if (DetailedAsserts.getValue(allocator.getOptions())) {
+        if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) {
             for (int i = 0; i < numUsePos(); i++) {
                 assert getUsePos(i) < splitPos;
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanEliminateSpillMovePhase.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanEliminateSpillMovePhase.java	Thu Aug 24 09:44:52 2017 +0200
@@ -23,7 +23,6 @@
 package org.graalvm.compiler.lir.alloc.trace.lsra;
 
 import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.asVariable;
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
@@ -34,6 +33,7 @@
 import org.graalvm.compiler.core.common.alloc.Trace;
 import org.graalvm.compiler.core.common.alloc.TraceBuilderResult;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.Indent;
 import org.graalvm.compiler.lir.LIRInsertionBuffer;
@@ -84,7 +84,7 @@
              * by Interval.spillDefinitionPos.
              */
             TraceInterval interval = allocator.createUnhandledListBySpillPos(spilledIntervals);
-            if (DetailedAsserts.getValue(allocator.getOptions())) {
+            if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) {
                 checkIntervals(debug, interval);
             }
             if (debug.isLogEnabled()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanPhase.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanPhase.java	Thu Aug 24 09:44:52 2017 +0200
@@ -27,7 +27,6 @@
 import static jdk.vm.ci.code.ValueUtil.isIllegal;
 import static jdk.vm.ci.code.ValueUtil.isLegal;
 import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
 
 import java.util.ArrayList;
@@ -39,6 +38,7 @@
 import org.graalvm.compiler.core.common.alloc.Trace;
 import org.graalvm.compiler.core.common.alloc.TraceBuilderResult;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.Indent;
@@ -603,7 +603,7 @@
 
                     TRACE_LINEAR_SCAN_ASSIGN_LOCATIONS_PHASE.apply(target, lirGenRes, trace, spillMoveFactory, registerAllocationConfig, traceBuilderResult, this, false);
 
-                    if (DetailedAsserts.getValue(options)) {
+                    if (Assertions.detailedAssertionsEnabled(options)) {
                         verifyIntervals();
                     }
                 } catch (Throwable e) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanResolveDataFlowPhase.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanResolveDataFlowPhase.java	Thu Aug 24 09:44:52 2017 +0200
@@ -23,7 +23,6 @@
 package org.graalvm.compiler.lir.alloc.trace.lsra;
 
 import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
 import static org.graalvm.compiler.lir.LIRValueUtil.asVariable;
 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
@@ -36,6 +35,7 @@
 import org.graalvm.compiler.core.common.alloc.Trace;
 import org.graalvm.compiler.core.common.alloc.TraceBuilderResult;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.Indent;
@@ -97,7 +97,7 @@
                     debug.log("inserting moves at beginning of toBlock B%d", toBlock.getId());
                 }
 
-                if (DetailedAsserts.getValue(allocator.getOptions())) {
+                if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) {
                     assert allocator.getLIR().getLIRforBlock(fromBlock).get(0) instanceof StandardOp.LabelOp : "block does not start with a label";
 
                     /*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Thu Aug 24 09:44:52 2017 +0200
@@ -34,11 +34,11 @@
 
 import org.graalvm.compiler.asm.AbstractAddress;
 import org.graalvm.compiler.asm.Assembler;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
 import org.graalvm.compiler.code.DataSection.Data;
 import org.graalvm.compiler.code.DataSection.RawData;
-import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.core.common.type.DataPointerConstant;
@@ -130,12 +130,12 @@
     /**
      * The LIR for which code is being generated.
      */
-    private LIR lir;
+    protected LIR lir;
 
     /**
      * The index of the block currently being emitted.
      */
-    private int currentBlockIndex;
+    protected int currentBlockIndex;
 
     /**
      * The object that emits code for managing a method's frame.
@@ -171,7 +171,7 @@
         assert frameContext != null;
         this.dataCache = dataCache;
 
-        if (dataBuilder.needDetailedPatchingInformation() || Assertions.ENABLED) {
+        if (dataBuilder.needDetailedPatchingInformation() || Assertions.assertionsEnabled()) {
             /*
              * Always enabled in debug mode, even when the VM does not request detailed information,
              * to increase test coverage.
@@ -313,6 +313,15 @@
     }
 
     /**
+     * Notifies this object of a branch instruction at offset {@code pos} in the code.
+     *
+     * @param isNegated negation status of the branch's condition.
+     */
+    @SuppressWarnings("unused")
+    public void recordBranch(int pos, boolean isNegated) {
+    }
+
+    /**
      * Returns the integer value of any constant that can be represented by a 32-bit integer value,
      * including long constants that fit into the 32-bit range.
      */
@@ -520,4 +529,5 @@
     public OptionValues getOptions() {
         return options;
     }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/AllocationStage.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/AllocationStage.java	Thu Aug 24 09:44:52 2017 +0200
@@ -24,7 +24,7 @@
 
 import static org.graalvm.compiler.core.common.GraalOptions.TraceRA;
 
-import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.lir.alloc.AllocationStageVerifier;
 import org.graalvm.compiler.lir.alloc.lsra.LinearScanPhase;
 import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessAnalysisPhase;
@@ -58,7 +58,7 @@
         // currently we mark locations only if we do register allocation
         appendPhase(new LocationMarkerPhase());
 
-        if (GraalOptions.DetailedAsserts.getValue(options)) {
+        if (Assertions.detailedAssertionsEnabled(options)) {
             appendPhase(new AllocationStageVerifier());
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPartialUnrollPhase.java	Thu Aug 24 09:44:52 2017 +0200
@@ -45,12 +45,12 @@
     protected void run(StructuredGraph graph, PhaseContext context) {
         if (graph.hasLoops()) {
             HashSetNodeEventListener listener = new HashSetNodeEventListener();
-            try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) {
-                boolean changed = true;
-                while (changed) {
+            boolean changed = true;
+            while (changed) {
+                changed = false;
+                try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) {
                     LoopsData dataCounted = new LoopsData(graph);
                     dataCounted.detectedCountedLoops();
-                    changed = false;
                     for (LoopEx loop : dataCounted.countedLoops()) {
                         if (!LoopTransformations.isUnrollableLoop(loop)) {
                             continue;
@@ -60,19 +60,20 @@
                                 // First perform the pre/post transformation and do the partial
                                 // unroll when we come around again.
                                 LoopTransformations.insertPrePostLoops(loop, graph);
-                                changed = true;
                             } else {
-                                changed |= LoopTransformations.partialUnroll(loop, graph);
+                                LoopTransformations.partialUnroll(loop, graph);
                             }
+                            changed = true;
                         }
                     }
                     dataCounted.deleteUnusedNodes();
+
+                    if (!listener.getNodes().isEmpty()) {
+                        canonicalizer.applyIncremental(graph, context, listener.getNodes());
+                        listener.getNodes().clear();
+                    }
                 }
             }
-            if (!listener.getNodes().isEmpty()) {
-                canonicalizer.applyIncremental(graph, context, listener.getNodes());
-                listener.getNodes().clear();
-            }
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java	Thu Aug 24 09:44:52 2017 +0200
@@ -31,16 +31,12 @@
 import java.util.List;
 
 import org.graalvm.compiler.core.common.RetryableBailoutException;
-import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Graph.Mark;
 import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.graph.NodeWorkList;
 import org.graalvm.compiler.graph.Position;
-import org.graalvm.compiler.loop.BasicInductionVariable;
 import org.graalvm.compiler.loop.CountedLoopInfo;
-import org.graalvm.compiler.loop.DerivedInductionVariable;
 import org.graalvm.compiler.loop.InductionVariable;
 import org.graalvm.compiler.loop.InductionVariable.Direction;
 import org.graalvm.compiler.loop.LoopEx;
@@ -59,20 +55,15 @@
 import org.graalvm.compiler.nodes.IfNode;
 import org.graalvm.compiler.nodes.LogicNode;
 import org.graalvm.compiler.nodes.LoopBeginNode;
-import org.graalvm.compiler.nodes.LoopEndNode;
 import org.graalvm.compiler.nodes.LoopExitNode;
 import org.graalvm.compiler.nodes.PhiNode;
+import org.graalvm.compiler.nodes.SafepointNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.ValuePhiNode;
-import org.graalvm.compiler.nodes.calc.AddNode;
-import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode;
 import org.graalvm.compiler.nodes.calc.CompareNode;
 import org.graalvm.compiler.nodes.calc.ConditionalNode;
 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
-import org.graalvm.compiler.nodes.calc.SubNode;
 import org.graalvm.compiler.nodes.extended.SwitchNode;
-import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
 import org.graalvm.compiler.phases.tiers.PhaseContext;
 
@@ -154,254 +145,13 @@
         // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms)
     }
 
-    public static boolean partialUnroll(LoopEx loop, StructuredGraph graph) {
+    public static void partialUnroll(LoopEx loop, StructuredGraph graph) {
         assert loop.loopBegin().isMainLoop();
         graph.getDebug().log("LoopPartialUnroll %s", loop);
-        boolean changed = false;
-        CountedLoopInfo mainCounted = loop.counted();
-        LoopBeginNode mainLoopBegin = loop.loopBegin();
-        InductionVariable iv = mainCounted.getCounter();
-        IfNode mainLimit = mainCounted.getLimitTest();
-        LogicNode ifTest = mainLimit.condition();
-        CompareNode compareNode = (CompareNode) ifTest;
-        ValueNode compareBound = null;
-        ValueNode curPhi = iv.valueNode();
-        if (compareNode.getX() == curPhi) {
-            compareBound = compareNode.getY();
-        } else if (compareNode.getY() == curPhi) {
-            compareBound = compareNode.getX();
-        }
+
         LoopFragmentInside newSegment = loop.inside().duplicate();
         newSegment.insertWithinAfter(loop);
-        graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, graph, "After duplication inside %s", mainLoopBegin);
-        ValueNode inductionNode = iv.valueNode();
-        Node newStrideNode = null;
-        for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
-            Node segmentOrigOp = null;
-            Node replacementOp = null;
-            changed = false;
-            // Rework each phi with a loop carried dependence
-            for (Node phiUsage : mainPhiNode.usages()) {
-                if (!loop.isOutsideLoop(phiUsage)) {
-                    for (int i = 1; i < mainPhiNode.valueCount(); i++) {
-                        ValueNode v = mainPhiNode.valueAt(i);
-                        if (mainPhiNode != inductionNode) {
-                            if (closureOnPhiInputToPhiUse(v, phiUsage, loop, graph)) {
-                                segmentOrigOp = v;
-                                Node node = newSegment.getDuplicatedNode(v);
-                                replacementOp = updateUnrollSegmentValue(mainPhiNode, inductionNode, phiUsage, v, newSegment);
 
-                                // Update the induction phi with new stride node
-                                mainPhiNode.setValueAt(i, (ValueNode) node);
-                                // This is for induction variables not referenced in the loop body
-                                if (inductionNode == v) {
-                                    newStrideNode = node;
-                                }
-                                changed = true;
-                                break;
-                            }
-                        } else if (v == phiUsage) {
-                            segmentOrigOp = phiUsage;
-                            Node node = newSegment.getDuplicatedNode(phiUsage);
-                            newStrideNode = node;
-                            replacementOp = updateUnrollSegmentValue(mainPhiNode, inductionNode, phiUsage, phiUsage, newSegment);
-
-                            // Update the induction phi with new stride node
-                            mainPhiNode.setValueAt(i, (ValueNode) node);
-                            changed = true;
-                            break;
-                        }
-                    }
-                }
-                if (changed) {
-                    break;
-                }
-            }
-
-            if (changed) {
-                // Patch the new segments induction uses of replacementOp with the old stride node
-                for (Node usage : mainPhiNode.usages()) {
-                    if (usage != segmentOrigOp) {
-                        if (!loop.isOutsideLoop(usage)) {
-                            Node node = newSegment.getDuplicatedNode(usage);
-                            if (node instanceof CompareNode) {
-                                continue;
-                            }
-                            node.replaceFirstInput(replacementOp, segmentOrigOp);
-                        }
-                    }
-                }
-            }
-        }
-
-        if (changed && newStrideNode == null) {
-            throw GraalError.shouldNotReachHere("Can't find stride node");
-        }
-        if (newStrideNode != null) {
-            // If merge the duplicate code into the loop and remove redundant code
-            placeNewSegmentAndCleanup(mainCounted, mainLoopBegin, newSegment);
-            int unrollFactor = mainLoopBegin.getUnrollFactor();
-            // First restore the old pattern of the loop exit condition so we can update it one way
-            if (unrollFactor > 1) {
-                if (compareBound instanceof SubNode) {
-                    SubNode newLimit = (SubNode) compareBound;
-                    ValueNode oldcompareBound = newLimit.getX();
-                    compareNode.replaceFirstInput(newLimit, oldcompareBound);
-                    newLimit.safeDelete();
-                    compareBound = oldcompareBound;
-                } else if (compareBound instanceof AddNode) {
-                    AddNode newLimit = (AddNode) compareBound;
-                    ValueNode oldcompareBound = newLimit.getX();
-                    compareNode.replaceFirstInput(newLimit, oldcompareBound);
-                    newLimit.safeDelete();
-                    compareBound = oldcompareBound;
-                }
-            }
-            unrollFactor *= 2;
-            mainLoopBegin.setUnrollFactor(unrollFactor);
-            // Reset stride to include new segment in loop control.
-            long oldStride = iv.constantStride() * 2;
-            // Now update the induction op and the exit condition
-            if (iv instanceof BasicInductionVariable) {
-                BasicInductionVariable biv = (BasicInductionVariable) iv;
-                BinaryArithmeticNode<?> newOp = (BinaryArithmeticNode<?>) newStrideNode;
-                Stamp strideStamp = newOp.stamp();
-                ConstantNode newStrideVal = graph.unique(ConstantNode.forIntegerStamp(strideStamp, oldStride));
-                newOp.setY(newStrideVal);
-                biv.setOP(newOp);
-                // Now use the current unrollFactor to update the exit condition to power of two
-                if (unrollFactor > 1) {
-                    if (iv.direction() == Direction.Up) {
-                        int modulas = (unrollFactor - 1);
-                        ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(strideStamp, modulas));
-                        ValueNode newLimit = graph.addWithoutUnique(new SubNode(compareBound, aboveVal));
-                        compareNode.replaceFirstInput(compareBound, newLimit);
-                    } else if (iv.direction() == Direction.Down) {
-                        int modulas = (unrollFactor - 1);
-                        ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(strideStamp, modulas));
-                        ValueNode newLimit = graph.addWithoutUnique(new AddNode(compareBound, aboveVal));
-                        compareNode.replaceFirstInput(compareBound, newLimit);
-                    }
-                }
-                mainLoopBegin.setLoopFrequency(mainLoopBegin.loopFrequency() / 2);
-            }
-            changed = true;
-        }
-        if (changed) {
-            graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "LoopPartialUnroll %s", loop);
-        }
-        return changed;
-    }
-
-    private static Node updateUnrollSegmentValue(PhiNode mainPhiNode, Node inductionNode, Node phiUsage, Node patchNode, LoopFragmentInside newSegment) {
-        Node node = newSegment.getDuplicatedNode(phiUsage);
-        assert node != null : phiUsage;
-        Node replacementOp = null;
-        int inputCnt = 0;
-        for (Node input : phiUsage.inputs()) {
-            inputCnt++;
-            if (input == mainPhiNode) {
-                break;
-            }
-        }
-        int newInputCnt = 0;
-        for (Node input : node.inputs()) {
-            newInputCnt++;
-            if (newInputCnt == inputCnt) {
-                replacementOp = input;
-                if (mainPhiNode == inductionNode) {
-                    node.replaceFirstInput(input, mainPhiNode);
-                } else {
-                    node.replaceFirstInput(input, patchNode);
-                }
-                break;
-            }
-        }
-        return replacementOp;
-    }
-
-    private static boolean closureOnPhiInputToPhiUse(Node inNode, Node usage, LoopEx loop, StructuredGraph graph) {
-        NodeWorkList nodes = graph.createNodeWorkList();
-        nodes.add(inNode);
-        // Now walk from the inNode to usage if we can find it else we do not have closure
-        for (Node node : nodes) {
-            if (node == usage) {
-                return true;
-            }
-            for (Node input : node.inputs()) {
-                if (!loop.isOutsideLoop(input)) {
-                    if (input != usage) {
-                        nodes.add(input);
-                    } else {
-                        return true;
-                        // For any reason if we have completed a closure, stop processing more
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    private static void placeNewSegmentAndCleanup(CountedLoopInfo mainCounted, LoopBeginNode mainLoopBegin, LoopFragmentInside newSegment) {
-        // Discard the segment entry and its flow, after if merging it into the loop
-        StructuredGraph graph = mainLoopBegin.graph();
-        IfNode loopTest = mainCounted.getLimitTest();
-        IfNode newSegmentTest = newSegment.getDuplicatedNode(loopTest);
-        AbstractBeginNode trueSuccessor = loopTest.trueSuccessor();
-        AbstractBeginNode falseSuccessor = loopTest.falseSuccessor();
-        FixedNode firstNode;
-        boolean codeInTrueSide = false;
-        if (trueSuccessor == mainCounted.getBody()) {
-            firstNode = trueSuccessor.next();
-            codeInTrueSide = true;
-        } else {
-            assert (falseSuccessor == mainCounted.getBody());
-            firstNode = falseSuccessor.next();
-        }
-        trueSuccessor = newSegmentTest.trueSuccessor();
-        falseSuccessor = newSegmentTest.falseSuccessor();
-        for (Node usage : falseSuccessor.anchored().snapshot()) {
-            usage.replaceFirstInput(falseSuccessor, loopTest.falseSuccessor());
-        }
-        for (Node usage : trueSuccessor.anchored().snapshot()) {
-            usage.replaceFirstInput(trueSuccessor, loopTest.trueSuccessor());
-        }
-        AbstractBeginNode startBlockNode;
-        if (codeInTrueSide) {
-            startBlockNode = trueSuccessor;
-        } else {
-            graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, mainLoopBegin.graph(), "before");
-            startBlockNode = falseSuccessor;
-        }
-        FixedNode lastNode = getBlockEnd(startBlockNode);
-        LoopEndNode loopEndNode = getSingleLoopEndFromLoop(mainLoopBegin);
-        FixedNode lastCodeNode = (FixedNode) loopEndNode.predecessor();
-        FixedNode newSegmentFirstNode = newSegment.getDuplicatedNode(firstNode);
-        FixedNode newSegmentLastNode = newSegment.getDuplicatedNode(lastCodeNode);
-        graph.getDebug().dump(DebugContext.DETAILED_LEVEL, loopEndNode.graph(), "Before placing segment");
-        if (firstNode instanceof LoopEndNode) {
-            GraphUtil.killCFG(newSegment.getDuplicatedNode(mainLoopBegin));
-        } else {
-            newSegmentLastNode.clearSuccessors();
-            startBlockNode.setNext(lastNode);
-            lastCodeNode.replaceFirstSuccessor(loopEndNode, newSegmentFirstNode);
-            newSegmentLastNode.replaceFirstSuccessor(lastNode, loopEndNode);
-            FixedWithNextNode oldLastNode = (FixedWithNextNode) lastCodeNode;
-            oldLastNode.setNext(newSegmentFirstNode);
-            FixedWithNextNode newLastNode = (FixedWithNextNode) newSegmentLastNode;
-            newLastNode.setNext(loopEndNode);
-            startBlockNode.clearSuccessors();
-            lastNode.safeDelete();
-            Node newSegmentTestStart = newSegmentTest.predecessor();
-            LogicNode newSegmentIfTest = newSegmentTest.condition();
-            newSegmentTestStart.clearSuccessors();
-            newSegmentTest.safeDelete();
-            newSegmentIfTest.safeDelete();
-            trueSuccessor.safeDelete();
-            falseSuccessor.safeDelete();
-            newSegmentTestStart.safeDelete();
-        }
-        graph.getDebug().dump(DebugContext.DETAILED_LEVEL, loopEndNode.graph(), "After placing segment");
     }
 
     // This function splits candidate loops into pre, main and post loops,
@@ -475,12 +225,12 @@
     public static void insertPrePostLoops(LoopEx loop, StructuredGraph graph) {
         graph.getDebug().log("LoopTransformations.insertPrePostLoops %s", loop);
         LoopFragmentWhole preLoop = loop.whole();
-        CountedLoopInfo preCounted = preLoop.loop().counted();
+        CountedLoopInfo preCounted = loop.counted();
         IfNode preLimit = preCounted.getLimitTest();
         if (preLimit != null) {
             LoopBeginNode preLoopBegin = loop.loopBegin();
             InductionVariable preIv = preCounted.getCounter();
-            LoopExitNode preLoopExitNode = getSingleExitFromLoop(preLoopBegin);
+            LoopExitNode preLoopExitNode = preLoopBegin.getSingleLoopExit();
             FixedNode continuationNode = preLoopExitNode.next();
 
             // Each duplication is inserted after the original, ergo create the post loop first
@@ -497,7 +247,7 @@
 
             EndNode postEndNode = getBlockEndAfterLoopExit(postLoopBegin);
             AbstractMergeNode postMergeNode = postEndNode.merge();
-            LoopExitNode postLoopExitNode = getSingleExitFromLoop(postLoopBegin);
+            LoopExitNode postLoopExitNode = postLoopBegin.getSingleLoopExit();
 
             // Update the main loop phi initialization to carry from the pre loop
             for (PhiNode prePhiNode : preLoopBegin.phis()) {
@@ -511,7 +261,7 @@
 
             // In the case of no Bounds tests, we just flow right into the main loop
             AbstractBeginNode mainLandingNode = BeginNode.begin(postEntryNode);
-            LoopExitNode mainLoopExitNode = getSingleExitFromLoop(mainLoopBegin);
+            LoopExitNode mainLoopExitNode = mainLoopBegin.getSingleLoopExit();
             mainLoopExitNode.setNext(mainLandingNode);
             preLoopExitNode.setNext(mainLoopBegin.forwardEnd());
 
@@ -528,6 +278,14 @@
             preLoopBegin.setLoopFrequency(1);
             mainLoopBegin.setLoopFrequency(Math.max(0.0, mainLoopBegin.loopFrequency() - 2));
             postLoopBegin.setLoopFrequency(Math.max(0.0, postLoopBegin.loopFrequency() - 1));
+
+            // The pre and post loops don't require safepoints at all
+            for (SafepointNode safepoint : preLoop.nodes().filter(SafepointNode.class)) {
+                graph.removeFixed(safepoint);
+            }
+            for (SafepointNode safepoint : postLoop.nodes().filter(SafepointNode.class)) {
+                graph.removeFixed(safepoint);
+            }
         }
         graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "InsertPrePostLoops %s", loop);
     }
@@ -573,21 +331,11 @@
         }
     }
 
-    private static LoopExitNode getSingleExitFromLoop(LoopBeginNode curLoopBegin) {
-        assert curLoopBegin.loopExits().count() == 1;
-        return curLoopBegin.loopExits().first();
-    }
-
-    private static LoopEndNode getSingleLoopEndFromLoop(LoopBeginNode curLoopBegin) {
-        assert curLoopBegin.loopEnds().count() == 1;
-        return curLoopBegin.loopEnds().first();
-    }
-
     /**
      * Find the end of the block following the LoopExit.
      */
     private static EndNode getBlockEndAfterLoopExit(LoopBeginNode curLoopBegin) {
-        FixedNode node = getSingleExitFromLoop(curLoopBegin).next();
+        FixedNode node = curLoopBegin.getSingleLoopExit().next();
         // Find the last node after the exit blocks starts
         return getBlockEnd(node);
     }
@@ -693,43 +441,18 @@
     }
 
     public static boolean isUnrollableLoop(LoopEx loop) {
-        if (!loop.isCounted()) {
+        if (!loop.isCounted() || !loop.counted().getCounter().isConstantStride() || !loop.loop().getChildren().isEmpty()) {
             return false;
         }
         LoopBeginNode loopBegin = loop.loopBegin();
-        boolean isCanonical = false;
         if (loopBegin.isMainLoop() || loopBegin.isSimpleLoop()) {
             // Flow-less loops to partial unroll for now. 3 blocks corresponds to an if that either
             // exits or continues the loop. There might be fixed and floating work within the loop
             // as well.
             if (loop.loop().getBlocks().size() < 3) {
-                isCanonical = true;
+                return true;
             }
         }
-        if (!isCanonical) {
-            return false;
-        }
-        for (ValuePhiNode phi : loopBegin.valuePhis()) {
-            if (phi.usages().filter(x -> loopBegin.isPhiAtMerge(x)).isNotEmpty()) {
-                // Filter out Phis which reference Phis at the same merge until the duplication
-                // logic handles it properly.
-                return false;
-            }
-            InductionVariable iv = loop.getInductionVariables().get(phi);
-            if (iv == null) {
-                continue;
-            }
-            if (iv instanceof DerivedInductionVariable) {
-                return false;
-            } else if (iv instanceof BasicInductionVariable) {
-                BasicInductionVariable biv = (BasicInductionVariable) iv;
-                if (!biv.isConstantStride()) {
-                    return false;
-                }
-            } else {
-                return false;
-            }
-        }
-        return true;
+        return false;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ReassociateInvariantPhase.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ReassociateInvariantPhase.java	Thu Aug 24 09:44:52 2017 +0200
@@ -26,24 +26,34 @@
 import org.graalvm.compiler.loop.LoopEx;
 import org.graalvm.compiler.loop.LoopsData;
 import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode;
 import org.graalvm.compiler.phases.Phase;
 
+/**
+ * Rearrange {@link BinaryArithmeticNode#isAssociative() associative binary operations} so that
+ * invariant parts of the expression can move outside of the loop.
+ */
 public class ReassociateInvariantPhase extends Phase {
 
     @SuppressWarnings("try")
     @Override
     protected void run(StructuredGraph graph) {
-        if (graph.hasLoops()) {
-            final LoopsData dataReassociate = new LoopsData(graph);
-            DebugContext debug = graph.getDebug();
-            try (DebugContext.Scope s = debug.scope("ReassociateInvariants")) {
+        int iterations = 0;
+        DebugContext debug = graph.getDebug();
+        try (DebugContext.Scope s = debug.scope("ReassociateInvariants")) {
+            boolean changed = true;
+            while (changed) {
+                changed = false;
+                final LoopsData dataReassociate = new LoopsData(graph);
                 for (LoopEx loop : dataReassociate.loops()) {
-                    loop.reassociateInvariants();
+                    changed |= loop.reassociateInvariants();
                 }
-            } catch (Throwable e) {
-                throw debug.handle(e);
+                dataReassociate.deleteUnusedNodes();
+                iterations++;
+                debug.dump(DebugContext.VERBOSE_LEVEL, graph, "after iteration %d", iterations);
             }
-            dataReassociate.deleteUnusedNodes();
+        } catch (Throwable e) {
+            throw debug.handle(e);
         }
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java	Thu Aug 24 09:44:52 2017 +0200
@@ -26,13 +26,12 @@
 import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.nodes.LoopBeginNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
-import org.junit.Ignore;
 import org.junit.Test;
 
 public class LoopPartialUnrollTest extends GraalCompilerTest {
 
     @Override
-    protected boolean checkLowTierGraph(StructuredGraph graph) {
+    protected boolean checkMidTierGraph(StructuredGraph graph) {
         NodeIterable<LoopBeginNode> loops = graph.getNodes().filter(LoopBeginNode.class);
         for (LoopBeginNode loop : loops) {
             if (loop.isMainLoop()) {
@@ -45,7 +44,7 @@
     public static long testMultiplySnippet(int arg) {
         long r = 1;
         for (int i = 0; branchProbability(0.99, i < arg); i++) {
-            r *= i;
+            r += r * i;
         }
         return r;
     }
@@ -59,7 +58,24 @@
         int c = 0;
         for (int i = 0; i < d; i++) {
             for (int j = 0; branchProbability(0.99, j < i); j++) {
-                c += j & 0x3;
+                c += c + j & 0x3;
+            }
+        }
+        return c;
+    }
+
+    @Test
+    public void testNestedSumBy2() {
+        for (int i = 0; i < 1000; i++) {
+            test("testNestedSumBy2Snippet", i);
+        }
+    }
+
+    public static int testNestedSumBy2Snippet(int d) {
+        int c = 0;
+        for (int i = 0; i < d; i++) {
+            for (int j = 0; branchProbability(0.99, j < i); j += 2) {
+                c += c + j & 0x3;
             }
         }
         return c;
@@ -75,7 +91,7 @@
     public static int testSumDownSnippet(int d) {
         int c = 0;
         for (int j = d; branchProbability(0.99, j > -4); j--) {
-            c += j & 0x3;
+            c += c + j & 0x3;
         }
         return c;
     }
@@ -83,21 +99,38 @@
     @Test
     public void testSumDown() {
         test("testSumDownSnippet", 1);
-        for (int i = 0; i < 8; i++) {
+        for (int i = 0; i < 160; i++) {
             test("testSumDownSnippet", i);
         }
     }
 
-    @Ignore("Phis which reference the backedge value of other Phis aren't handled properly")
+    public static int testSumDownBy2Snippet(int d) {
+        int c = 0;
+        for (int j = d; branchProbability(0.99, j > -4); j -= 2) {
+            c += c + j & 0x3;
+        }
+        return c;
+    }
+
+    @Test
+    public void testSumDownBy2() {
+        test("testSumDownBy2Snippet", 1);
+        for (int i = 0; i < 160; i++) {
+            test("testSumDownBy2Snippet", i);
+        }
+    }
+
     @Test
     public void testLoopCarried() {
         test("testLoopCarriedSnippet", 1, 2);
+        test("testLoopCarriedSnippet", 0, 4);
+        test("testLoopCarriedSnippet", 4, 0);
     }
 
     public static int testLoopCarriedSnippet(int a, int b) {
         int c = a;
         int d = b;
-        for (int j = 0; j < a; j++) {
+        for (int j = 0; branchProbability(0.99, j < a); j++) {
             d = c;
             c += 1;
         }
@@ -136,4 +169,16 @@
         test("testComplexSnippet", 1000);
     }
 
+    public static long testSignExtensionSnippet(long arg) {
+        long r = 1;
+        for (int i = 0; branchProbability(0.99, i < arg); i++) {
+            r *= i;
+        }
+        return r;
+    }
+
+    @Test
+    public void testSignExtension() {
+        test("testSignExtensionSnippet", 9L);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java	Mon Aug 21 14:05:14 2017 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java	Thu Aug 24 09:44:52 2017 +0200
@@ -22,15 +22,13 @@
  */
 package org.graalvm.compiler.loop;
 
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.Queue;
-
+import jdk.vm.ci.code.BytecodeFrame;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeBitMap;
 import org.graalvm.compiler.graph.iterators.NodePredicate;
@@ -72,7 +70,9 @@
 import org.graalvm.util.EconomicSet;
 import org.graalvm.util.Equivalence;
 
-import jdk.vm.ci.code.BytecodeFrame;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Queue;
 
 public class LoopEx {
     private final Loop<Block> loop;
@@ -164,33 +164,46 @@
 
     private class InvariantPredicate implements NodePredicate {
 
+        private final Graph.Mark mark;
+
+        InvariantPredicate() {
+            this.mark = loopBegin().graph().getMark();
+        }
+
         @Override
         public boolean apply(Node n) {
+            if (loopBegin().graph().isNew(mark, n)) {
+                // Newly created nodes are unknown.
+                return false;
+            }
             return isOutsideLoop(n);