Merge
authorduke
Wed, 05 Jul 2017 20:45:16 +0200
changeset 32091 98a47476a744
parent 32090 7bf24ea31a4d (diff)
parent 32068 6e6ce42fc702 (current diff)
child 32148 f39200e38da3
Merge
--- a/hotspot/.hgtags	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 20:45:16 2017 +0200
@@ -479,3 +479,4 @@
 fff6b54e9770ac4c12c2fb4cab5aa7672affa4bd jdk9-b74
 2f354281e9915275693c4e519a959b8a6f22d3a3 jdk9-b75
 0bc8d1656d6f2b1fdfe803c1305a108bb9939f35 jdk9-b76
+e66c3813789debfc06f206afde1bf7a84cb08451 jdk9-b77
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad	Wed Jul 05 20:45:16 2017 +0200
@@ -2389,9 +2389,11 @@
   // Note that the code buffer's insts_mark is always relative to insts.
   // That's why we must use the macroassembler to generate a handler.
   MacroAssembler _masm(&cbuf);
-  address base =
-  __ start_a_stub(size_exception_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
+  address base = __ start_a_stub(size_exception_handler());
+  if (base == NULL) {
+    ciEnv::current()->record_failure("CodeCache is full");
+    return 0;  // CodeBuffer::expand failed
+  }
   int offset = __ offset();
   __ far_jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point()));
   assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
@@ -2405,9 +2407,11 @@
   // Note that the code buffer's insts_mark is always relative to insts.
   // That's why we must use the macroassembler to generate a handler.
   MacroAssembler _masm(&cbuf);
-  address base =
-  __ start_a_stub(size_deopt_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
+  address base = __ start_a_stub(size_deopt_handler());
+  if (base == NULL) {
+    ciEnv::current()->record_failure("CodeCache is full");
+    return 0;  // CodeBuffer::expand failed
+  }
   int offset = __ offset();
 
   __ adr(lr, __ pc());
@@ -3657,24 +3661,37 @@
     MacroAssembler _masm(&cbuf);
 
     address addr = (address)$meth$$method;
+    address call;
     if (!_method) {
       // A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap.
-      __ trampoline_call(Address(addr, relocInfo::runtime_call_type), &cbuf);
+      call = __ trampoline_call(Address(addr, relocInfo::runtime_call_type), &cbuf);
     } else if (_optimized_virtual) {
-      __ trampoline_call(Address(addr, relocInfo::opt_virtual_call_type), &cbuf);
+      call = __ trampoline_call(Address(addr, relocInfo::opt_virtual_call_type), &cbuf);
     } else {
-      __ trampoline_call(Address(addr, relocInfo::static_call_type), &cbuf);
+      call = __ trampoline_call(Address(addr, relocInfo::static_call_type), &cbuf);
+    }
+    if (call == NULL) {
+      ciEnv::current()->record_failure("CodeCache is full"); 
+      return;
     }
 
     if (_method) {
       // Emit stub for static call
-      CompiledStaticCall::emit_to_interp_stub(cbuf);
+      address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+      if (stub == NULL) {
+        ciEnv::current()->record_failure("CodeCache is full"); 
+        return;
+      }
     }
   %}
 
   enc_class aarch64_enc_java_dynamic_call(method meth) %{
     MacroAssembler _masm(&cbuf);
-    __ ic_call((address)$meth$$method);
+    address call = __ ic_call((address)$meth$$method);
+    if (call == NULL) {
+      ciEnv::current()->record_failure("CodeCache is full"); 
+      return;
+    }
   %}
 
   enc_class aarch64_enc_call_epilog() %{
@@ -3695,7 +3712,11 @@
     address entry = (address)$meth$$method;
     CodeBlob *cb = CodeCache::find_blob(entry);
     if (cb) {
-      __ trampoline_call(Address(entry, relocInfo::runtime_call_type));
+      address call = __ trampoline_call(Address(entry, relocInfo::runtime_call_type));
+      if (call == NULL) {
+        ciEnv::current()->record_failure("CodeCache is full"); 
+        return;
+      }
     } else {
       int gpcnt;
       int fpcnt;
--- a/hotspot/src/cpu/aarch64/vm/c1_CodeStubs_aarch64.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/c1_CodeStubs_aarch64.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -327,9 +327,16 @@
   ce->align_call(lir_static_call);
 
   ce->emit_static_call_stub();
+  if (ce->compilation()->bailed_out()) {
+    return; // CodeCache is full
+  }
   Address resolve(SharedRuntime::get_resolve_static_call_stub(),
                   relocInfo::static_call_type);
-  __ trampoline_call(resolve);
+  address call = __ trampoline_call(resolve);
+  if (call == NULL) {
+    ce->bailout("trampoline stub overflow");
+    return;
+  }
   ce->add_call_info_here(info());
 
 #ifndef PRODUCT
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1996,13 +1996,21 @@
 
 
 void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
-  __ trampoline_call(Address(op->addr(), rtype));
+  address call = __ trampoline_call(Address(op->addr(), rtype));
+  if (call == NULL) {
+    bailout("trampoline stub overflow");
+    return;
+  }
   add_call_info(code_offset(), op->info());
 }
 
 
 void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
-  __ ic_call(op->addr());
+  address call = __ ic_call(op->addr());
+  if (call == NULL) {
+    bailout("trampoline stub overflow");
+    return;
+  }
   add_call_info(code_offset(), op->info());
 }
 
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -26,6 +26,9 @@
 #ifndef CPU_X86_VM_C1_LIRASSEMBLER_X86_HPP
 #define CPU_X86_VM_C1_LIRASSEMBLER_X86_HPP
 
+// ArrayCopyStub needs access to bailout
+friend class ArrayCopyStub;
+
  private:
 
   int array_element_size(BasicType type) const;
--- a/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -51,7 +51,7 @@
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
-void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
   // Stub is fixed up when the corresponding call is converted from
   // calling compiled code to calling interpreted code.
   // mov rmethod, 0
@@ -63,10 +63,11 @@
   // That's why we must use the macroassembler to generate a stub.
   MacroAssembler _masm(&cbuf);
 
-  address base = __ start_a_stub(to_interp_stub_size()*2);
-
+  address base = __ start_a_stub(to_interp_stub_size());
   int offset = __ offset();
-  if (base == NULL)  return;  // CodeBuffer::expand failed
+  if (base == NULL) {
+    return NULL;  // CodeBuffer::expand failed
+  }
   // static stub relocation stores the instruction address of the call
   __ relocate(static_stub_Relocation::spec(mark));
   // static stub relocation also tags the Method* in the code-stream.
@@ -76,6 +77,7 @@
 
   assert((__ offset() - offset) <= (int)to_interp_stub_size(), "stub too big");
   __ end_a_stub();
+  return base;
 }
 #undef __
 
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -664,7 +664,7 @@
 // Maybe emit a call via a trampoline.  If the code cache is small
 // trampolines won't be emitted.
 
-void MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) {
+address MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) {
   assert(entry.rspec().type() == relocInfo::runtime_call_type
          || entry.rspec().type() == relocInfo::opt_virtual_call_type
          || entry.rspec().type() == relocInfo::static_call_type
@@ -672,7 +672,10 @@
 
   unsigned int start_offset = offset();
   if (far_branches() && !Compile::current()->in_scratch_emit_size()) {
-    emit_trampoline_stub(offset(), entry.target());
+    address stub = emit_trampoline_stub(start_offset, entry.target());
+    if (stub == NULL) {
+      return NULL; // CodeCache is full
+    }
   }
 
   if (cbuf) cbuf->set_insts_mark();
@@ -682,6 +685,8 @@
   } else {
     bl(pc());
   }
+  // just need to return a non-null address
+  return pc();
 }
 
 
@@ -696,13 +701,11 @@
 //   load the call target from the constant pool
 //   branch (LR still points to the call site above)
 
-void MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
+address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
                                              address dest) {
   address stub = start_a_stub(Compile::MAX_stubs_size/2);
   if (stub == NULL) {
-    start_a_stub(Compile::MAX_stubs_size/2);
-    Compile::current()->env()->record_out_of_memory_failure();
-    return;
+    return NULL;  // CodeBuffer::expand failed
   }
 
   // Create a trampoline stub relocation which relates this trampoline stub
@@ -729,15 +732,16 @@
   assert(is_NativeCallTrampolineStub_at(stub_start_addr), "doesn't look like a trampoline");
 
   end_a_stub();
+  return stub;
 }
 
-void MacroAssembler::ic_call(address entry) {
+address MacroAssembler::ic_call(address entry) {
   RelocationHolder rh = virtual_call_Relocation::spec(pc());
   // address const_ptr = long_constant((jlong)Universe::non_oop_word());
   // unsigned long offset;
   // ldr_constant(rscratch2, const_ptr);
   movptr(rscratch2, (uintptr_t)Universe::non_oop_word());
-  trampoline_call(Address(entry, rh));
+  return trampoline_call(Address(entry, rh));
 }
 
 // Implementation of call_VM versions
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -539,7 +539,7 @@
 
   static int patch_oop(address insn_addr, address o);
 
-  void emit_trampoline_stub(int insts_call_instruction_offset, address target);
+  address emit_trampoline_stub(int insts_call_instruction_offset, address target);
 
   // The following 4 methods return the offset of the appropriate move instruction
 
@@ -942,7 +942,7 @@
 
   // Calls
 
-  void trampoline_call(Address entry, CodeBuffer *cbuf = NULL);
+  address trampoline_call(Address entry, CodeBuffer *cbuf = NULL);
 
   static bool far_branches() {
     return ReservedCodeCacheSize > branch_range;
@@ -962,7 +962,7 @@
   }
 
   // Emit the CompiledIC call idiom
-  void ic_call(address entry);
+  address ic_call(address entry);
 
 public:
 
--- a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -94,7 +94,7 @@
 
 const int IC_pos_in_java_to_interp_stub = 8;
 #define __ _masm.
-void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
 #ifdef COMPILER2
   // Get the mark within main instrs section which is set to the address of the call.
   address call_addr = cbuf.insts_mark();
@@ -106,8 +106,7 @@
   // Start the stub.
   address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());
   if (stub == NULL) {
-    Compile::current()->env()->record_out_of_memory_failure();
-    return;
+    return NULL; // CodeCache is full
   }
 
   // For java_to_interp stubs we use R11_scratch1 as scratch register
@@ -149,6 +148,7 @@
 
  // End the stub.
   __ end_a_stub();
+  return stub;
 #else
   ShouldNotReachHere();
 #endif
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -2187,7 +2187,7 @@
 }
 
 void InterpreterMacroAssembler::increment_invocation_counter(Register Rcounters, Register iv_be_count, Register Rtmp_r0) {
-  assert(UseCompiler, "incrementing must be useful");
+  assert(UseCompiler || LogTouchedMethods, "incrementing must be useful");
   Register invocation_count = iv_be_count;
   Register backedge_count   = Rtmp_r0;
   int delta = InvocationCounter::count_increment;
--- a/hotspot/src/cpu/ppc/vm/ppc.ad	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad	Wed Jul 05 20:45:16 2017 +0200
@@ -1082,7 +1082,7 @@
   // Start the stub.
   address stub = __ start_a_stub(Compile::MAX_stubs_size/2);
   if (stub == NULL) {
-    Compile::current()->env()->record_out_of_memory_failure();
+    ciEnv::current()->record_failure("CodeCache is full");
     return;
   }
 
@@ -1160,7 +1160,7 @@
 
     // Emit the trampoline stub which will be related to the branch-and-link below.
     CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset);
-    if (Compile::current()->env()->failing()) { return offsets; } // Code cache may be full.
+    if (ciEnv::current()->failing()) { return offsets; } // Code cache may be full.
     __ relocate(rtype);
   }
 
@@ -3397,7 +3397,7 @@
 
         // Emit the trampoline stub which will be related to the branch-and-link below.
         CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
-        if (Compile::current()->env()->failing()) { return; } // Code cache may be full.
+        if (ciEnv::current()->failing()) { return; } // Code cache may be full.
         __ relocate(_optimized_virtual ?
                     relocInfo::opt_virtual_call_type : relocInfo::static_call_type);
       }
@@ -3410,7 +3410,11 @@
       __ bl(__ pc());  // Emits a relocation.
 
       // The stub for call to interpreter.
-      CompiledStaticCall::emit_to_interp_stub(cbuf);
+      address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+      if (stub == NULL) {
+        ciEnv::current()->record_failure("CodeCache is full"); 
+        return;
+      }
     }
   %}
 
@@ -3455,7 +3459,11 @@
 
     assert(_method, "execute next statement conditionally");
     // The stub for call to interpreter.
-    CompiledStaticCall::emit_to_interp_stub(cbuf);
+    address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+    if (stub == NULL) {
+      ciEnv::current()->record_failure("CodeCache is full"); 
+      return;
+    }
 
     // Restore original sp.
     __ ld(R11_scratch1, 0, R1_SP); // Load caller sp.
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -432,6 +432,9 @@
   __ mov(length()->as_register(),  O4);
 
   ce->emit_static_call_stub();
+  if (ce->compilation()->bailed_out()) {
+    return; // CodeCache is full
+  }
 
   __ call(SharedRuntime::get_resolve_static_call_stub(), relocInfo::static_call_type);
   __ delayed()->nop();
--- a/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -53,7 +53,7 @@
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
-void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
 #ifdef COMPILER2
   // Stub is fixed up when the corresponding call is converted from calling
   // compiled code to calling interpreted code.
@@ -64,9 +64,10 @@
 
   MacroAssembler _masm(&cbuf);
 
-  address base =
-  __ start_a_stub(to_interp_stub_size()*2);
-  if (base == NULL) return;  // CodeBuffer::expand failed.
+  address base = __ start_a_stub(to_interp_stub_size());
+  if (base == NULL) {
+    return NULL;  // CodeBuffer::expand failed.
+  }
 
   // Static stub relocation stores the instruction address of the call.
   __ relocate(static_stub_Relocation::spec(mark));
@@ -81,6 +82,7 @@
 
   // Update current stubs pointer and restore code_end.
   __ end_a_stub();
+  return base;
 #else
   ShouldNotReachHere();
 #endif
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -2314,7 +2314,7 @@
 }
 
 void InterpreterMacroAssembler::increment_invocation_counter( Register Rcounters, Register Rtmp, Register Rtmp2 ) {
-  assert(UseCompiler, "incrementing must be useful");
+  assert(UseCompiler || LogTouchedMethods, "incrementing must be useful");
   assert_different_registers(Rcounters, Rtmp, Rtmp2);
 
   Address inv_counter(Rcounters, MethodCounters::invocation_counter_offset() +
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Jul 05 20:45:16 2017 +0200
@@ -1773,9 +1773,11 @@
   AddressLiteral exception_blob(OptoRuntime::exception_blob()->entry_point());
   MacroAssembler _masm(&cbuf);
 
-  address base =
-  __ start_a_stub(size_exception_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
+  address base = __ start_a_stub(size_exception_handler());
+  if (base == NULL) {
+    ciEnv::current()->record_failure("CodeCache is full");
+    return 0;  // CodeBuffer::expand failed
+  }
 
   int offset = __ offset();
 
@@ -1796,9 +1798,11 @@
   AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack());
   MacroAssembler _masm(&cbuf);
 
-  address base =
-  __ start_a_stub(size_deopt_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
+  address base = __ start_a_stub(size_deopt_handler());
+  if (base == NULL) {
+    ciEnv::current()->record_failure("CodeCache is full");
+    return 0;  // CodeBuffer::expand failed
+  }
 
   int offset = __ offset();
   __ save_frame(0);
@@ -2599,7 +2603,12 @@
       emit_call_reloc(cbuf, $meth$$method, relocInfo::static_call_type);
     }
     if (_method) {  // Emit stub for static call.
-      CompiledStaticCall::emit_to_interp_stub(cbuf);
+      address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+      // Stub does not fit into scratch buffer if TraceJumps is enabled
+      if (stub == NULL && !(TraceJumps && Compile::current()->in_scratch_emit_size())) {
+        ciEnv::current()->record_failure("CodeCache is full");
+        return;
+      } 
     }
   %}
 
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -503,6 +503,9 @@
   ce->align_call(lir_static_call);
 
   ce->emit_static_call_stub();
+  if (ce->compilation()->bailed_out()) {
+    return; // CodeCache is full
+  }
   AddressLiteral resolve(SharedRuntime::get_resolve_static_call_stub(),
                          relocInfo::static_call_type);
   __ call(resolve);
--- a/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -50,7 +50,7 @@
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
-void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
   // Stub is fixed up when the corresponding call is converted from
   // calling compiled code to calling interpreted code.
   // movq rbx, 0
@@ -62,9 +62,10 @@
   // That's why we must use the macroassembler to generate a stub.
   MacroAssembler _masm(&cbuf);
 
-  address base =
-  __ start_a_stub(to_interp_stub_size()*2);
-  if (base == NULL) return;  // CodeBuffer::expand failed.
+  address base = __ start_a_stub(to_interp_stub_size());
+  if (base == NULL) {
+    return NULL;  // CodeBuffer::expand failed.
+  }
   // Static stub relocation stores the instruction address of the call.
   __ relocate(static_stub_Relocation::spec(mark), Assembler::imm_operand);
   // Static stub relocation also tags the Method* in the code-stream.
@@ -74,6 +75,7 @@
 
   // Update current stubs pointer and restore insts_end.
   __ end_a_stub();
+  return base;
 }
 #undef __
 
--- a/hotspot/src/cpu/x86/vm/x86.ad	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/x86.ad	Wed Jul 05 20:45:16 2017 +0200
@@ -1594,7 +1594,10 @@
   // That's why we must use the macroassembler to generate a handler.
   MacroAssembler _masm(&cbuf);
   address base = __ start_a_stub(size_exception_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
+  if (base == NULL) {
+    ciEnv::current()->record_failure("CodeCache is full");
+    return 0;  // CodeBuffer::expand failed
+  }
   int offset = __ offset();
   __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point()));
   assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
@@ -1609,7 +1612,10 @@
   // That's why we must use the macroassembler to generate a handler.
   MacroAssembler _masm(&cbuf);
   address base = __ start_a_stub(size_deopt_handler());
-  if (base == NULL)  return 0;  // CodeBuffer::expand failed
+  if (base == NULL) {
+    ciEnv::current()->record_failure("CodeCache is full");
+    return 0;  // CodeBuffer::expand failed
+  }
   int offset = __ offset();
 
 #ifdef _LP64
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Jul 05 20:45:16 2017 +0200
@@ -1907,7 +1907,11 @@
                      static_call_Relocation::spec(), RELOC_IMM32 );
     }
     if (_method) {  // Emit stub for static call.
-      CompiledStaticCall::emit_to_interp_stub(cbuf);
+      address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+      if (stub == NULL) {
+        ciEnv::current()->record_failure("CodeCache is full");
+        return;
+      } 
     }
   %}
 
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Jul 05 20:45:16 2017 +0200
@@ -2137,7 +2137,11 @@
     }
     if (_method) {
       // Emit stub for static call.
-      CompiledStaticCall::emit_to_interp_stub(cbuf);
+      address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+      if (stub == NULL) {
+        ciEnv::current()->record_failure("CodeCache is full");
+        return;
+      } 
     }
   %}
 
--- a/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -60,8 +60,9 @@
 
 // ----------------------------------------------------------------------------
 
-void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
   ShouldNotReachHere(); // Only needed for COMPILER2.
+  return NULL;
 }
 
 int CompiledStaticCall::to_interp_stub_size() {
--- a/hotspot/src/os/aix/vm/os_aix.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -971,34 +971,32 @@
   guarantee(pthread_attr_setsuspendstate_np(&attr, PTHREAD_CREATE_SUSPENDED_NP) == 0, "???");
 
   // calculate stack size if it's not specified by caller
-  if (os::Aix::supports_variable_stack_size()) {
-    if (stack_size == 0) {
-      stack_size = os::Aix::default_stack_size(thr_type);
-
-      switch (thr_type) {
-      case os::java_thread:
-        // Java threads use ThreadStackSize whose default value can be changed with the flag -Xss.
-        assert(JavaThread::stack_size_at_create() > 0, "this should be set");
-        stack_size = JavaThread::stack_size_at_create();
+  if (stack_size == 0) {
+    stack_size = os::Aix::default_stack_size(thr_type);
+
+    switch (thr_type) {
+    case os::java_thread:
+      // Java threads use ThreadStackSize whose default value can be changed with the flag -Xss.
+      assert(JavaThread::stack_size_at_create() > 0, "this should be set");
+      stack_size = JavaThread::stack_size_at_create();
+      break;
+    case os::compiler_thread:
+      if (CompilerThreadStackSize > 0) {
+        stack_size = (size_t)(CompilerThreadStackSize * K);
         break;
-      case os::compiler_thread:
-        if (CompilerThreadStackSize > 0) {
-          stack_size = (size_t)(CompilerThreadStackSize * K);
-          break;
-        } // else fall through:
-          // use VMThreadStackSize if CompilerThreadStackSize is not defined
-      case os::vm_thread:
-      case os::pgc_thread:
-      case os::cgc_thread:
-      case os::watcher_thread:
-        if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
-        break;
-      }
+      } // else fall through:
+        // use VMThreadStackSize if CompilerThreadStackSize is not defined
+    case os::vm_thread:
+    case os::pgc_thread:
+    case os::cgc_thread:
+    case os::watcher_thread:
+      if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
+      break;
     }
-
-    stack_size = MAX2(stack_size, os::Aix::min_stack_allowed);
-    pthread_attr_setstacksize(&attr, stack_size);
-  } //else let thread_create() pick the default value (96 K on AIX)
+  }
+
+  stack_size = MAX2(stack_size, os::Aix::min_stack_allowed);
+  pthread_attr_setstacksize(&attr, stack_size);
 
   pthread_t tid;
   int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
--- a/hotspot/src/os/aix/vm/os_aix.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -131,8 +131,6 @@
   static void initialize_libo4();
   static void initialize_libperfstat();
 
-  static bool supports_variable_stack_size();
-
  public:
   static void init_thread_fpu_state();
   static pthread_t main_thread(void)                                { return _main_thread; }
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -739,40 +739,35 @@
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
-  // stack size
-  if (os::Bsd::supports_variable_stack_size()) {
-    // calculate stack size if it's not specified by caller
-    if (stack_size == 0) {
-      stack_size = os::Bsd::default_stack_size(thr_type);
-
-      switch (thr_type) {
-      case os::java_thread:
-        // Java threads use ThreadStackSize which default value can be
-        // changed with the flag -Xss
-        assert(JavaThread::stack_size_at_create() > 0, "this should be set");
-        stack_size = JavaThread::stack_size_at_create();
+  // calculate stack size if it's not specified by caller
+  if (stack_size == 0) {
+    stack_size = os::Bsd::default_stack_size(thr_type);
+
+    switch (thr_type) {
+    case os::java_thread:
+      // Java threads use ThreadStackSize which default value can be
+      // changed with the flag -Xss
+      assert(JavaThread::stack_size_at_create() > 0, "this should be set");
+      stack_size = JavaThread::stack_size_at_create();
+      break;
+    case os::compiler_thread:
+      if (CompilerThreadStackSize > 0) {
+        stack_size = (size_t)(CompilerThreadStackSize * K);
         break;
-      case os::compiler_thread:
-        if (CompilerThreadStackSize > 0) {
-          stack_size = (size_t)(CompilerThreadStackSize * K);
-          break;
-        } // else fall through:
-          // use VMThreadStackSize if CompilerThreadStackSize is not defined
-      case os::vm_thread:
-      case os::pgc_thread:
-      case os::cgc_thread:
-      case os::watcher_thread:
-        if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
-        break;
-      }
+      } // else fall through:
+        // use VMThreadStackSize if CompilerThreadStackSize is not defined
+    case os::vm_thread:
+    case os::pgc_thread:
+    case os::cgc_thread:
+    case os::watcher_thread:
+      if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
+      break;
     }
-
-    stack_size = MAX2(stack_size, os::Bsd::min_stack_allowed);
-    pthread_attr_setstacksize(&attr, stack_size);
-  } else {
-    // let pthread_create() pick the default value.
   }
 
+  stack_size = MAX2(stack_size, os::Bsd::min_stack_allowed);
+  pthread_attr_setstacksize(&attr, stack_size);
+
   ThreadState state;
 
   {
--- a/hotspot/src/os/bsd/vm/os_bsd.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,8 +75,6 @@
   static julong physical_memory() { return _physical_memory; }
   static void initialize_system_info();
 
-  static bool supports_variable_stack_size();
-
   static void rebuild_cpu_to_node_map();
   static GrowableArray<int>* cpu_to_node()    { return _cpu_to_node; }
 
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -653,8 +653,7 @@
   OSThread* osthread = thread->osthread();
   Monitor* sync = osthread->startThread_lock();
 
-  // thread_id is kernel thread id (similar to Solaris LWP id)
-  osthread->set_thread_id(os::Linux::gettid());
+  osthread->set_thread_id(os::current_thread_id());
 
   if (UseNUMA) {
     int lgrp_id = os::numa_get_group_id();
@@ -712,38 +711,34 @@
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 
   // stack size
-  if (os::Linux::supports_variable_stack_size()) {
-    // calculate stack size if it's not specified by caller
-    if (stack_size == 0) {
-      stack_size = os::Linux::default_stack_size(thr_type);
-
-      switch (thr_type) {
-      case os::java_thread:
-        // Java threads use ThreadStackSize which default value can be
-        // changed with the flag -Xss
-        assert(JavaThread::stack_size_at_create() > 0, "this should be set");
-        stack_size = JavaThread::stack_size_at_create();
+  // calculate stack size if it's not specified by caller
+  if (stack_size == 0) {
+    stack_size = os::Linux::default_stack_size(thr_type);
+
+    switch (thr_type) {
+    case os::java_thread:
+      // Java threads use ThreadStackSize which default value can be
+      // changed with the flag -Xss
+      assert(JavaThread::stack_size_at_create() > 0, "this should be set");
+      stack_size = JavaThread::stack_size_at_create();
+      break;
+    case os::compiler_thread:
+      if (CompilerThreadStackSize > 0) {
+        stack_size = (size_t)(CompilerThreadStackSize * K);
         break;
-      case os::compiler_thread:
-        if (CompilerThreadStackSize > 0) {
-          stack_size = (size_t)(CompilerThreadStackSize * K);
-          break;
-        } // else fall through:
-          // use VMThreadStackSize if CompilerThreadStackSize is not defined
-      case os::vm_thread:
-      case os::pgc_thread:
-      case os::cgc_thread:
-      case os::watcher_thread:
-        if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
-        break;
-      }
+      } // else fall through:
+        // use VMThreadStackSize if CompilerThreadStackSize is not defined
+    case os::vm_thread:
+    case os::pgc_thread:
+    case os::cgc_thread:
+    case os::watcher_thread:
+      if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
+      break;
     }
-
-    stack_size = MAX2(stack_size, os::Linux::min_stack_allowed);
-    pthread_attr_setstacksize(&attr, stack_size);
-  } else {
-    // let pthread_create() pick the default value.
-  }
+  }
+
+  stack_size = MAX2(stack_size, os::Linux::min_stack_allowed);
+  pthread_attr_setstacksize(&attr, stack_size);
 
   // glibc guard page
   pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));
@@ -1424,7 +1419,8 @@
   return n;
 }
 
-intx os::current_thread_id() { return (intx)pthread_self(); }
+// thread_id is kernel thread id (similar to Solaris LWP id)
+intx os::current_thread_id() { return os::Linux::gettid(); }
 int os::current_process_id() {
   return ::getpid();
 }
--- a/hotspot/src/os/linux/vm/os_linux.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -83,8 +83,6 @@
   static void set_glibc_version(const char *s)      { _glibc_version = s; }
   static void set_libpthread_version(const char *s) { _libpthread_version = s; }
 
-  static bool supports_variable_stack_size();
-
   static void rebuild_cpu_to_node_map();
   static GrowableArray<int>* cpu_to_node()    { return _cpu_to_node; }
 
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2012, 2014 SAP AG. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -489,10 +489,6 @@
 
 size_t os::Aix::min_stack_allowed = 128*K;
 
-// Aix is always in floating stack mode. The stack size for a new
-// thread can be set via pthread_attr_setstacksize().
-bool os::Aix::supports_variable_stack_size() { return true; }
-
 // return default stack size for thr_type
 size_t os::Aix::default_stack_size(os::ThreadType thr_type) {
   // default stack size (compiler thread needs larger stack)
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -780,9 +780,6 @@
 
 #ifdef AMD64
 size_t os::Bsd::min_stack_allowed  = 64 * K;
-
-// amd64: pthread on amd64 is always in floating stack mode
-bool os::Bsd::supports_variable_stack_size() {  return true; }
 #else
 size_t os::Bsd::min_stack_allowed  =  (48 DEBUG_ONLY(+4))*K;
 
@@ -790,7 +787,6 @@
 #define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
 #endif
 
-bool os::Bsd::supports_variable_stack_size() { return true; }
 #endif // AMD64
 
 // return default stack size for thr_type
--- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -290,10 +290,6 @@
 
 size_t os::Bsd::min_stack_allowed = 64 * K;
 
-bool os::Bsd::supports_variable_stack_size() {
-  return true;
-}
-
 size_t os::Bsd::default_stack_size(os::ThreadType thr_type) {
 #ifdef _LP64
   size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -496,9 +496,6 @@
 
 size_t os::Linux::min_stack_allowed  = 64 * K;
 
-// aarch64: pthread on aarch64 is always in floating stack mode
-bool os::Linux::supports_variable_stack_size() {  return true; }
-
 // return default stack size for thr_type
 size_t os::Linux::default_stack_size(os::ThreadType thr_type) {
   // default stack size (compiler thread needs larger stack)
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -467,8 +467,6 @@
 
 size_t os::Linux::min_stack_allowed = 128*K;
 
-bool os::Linux::supports_variable_stack_size() { return true; }
-
 // return default stack size for thr_type
 size_t os::Linux::default_stack_size(os::ThreadType thr_type) {
   // default stack size (compiler thread needs larger stack)
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -733,9 +733,6 @@
 
 size_t os::Linux::min_stack_allowed  = 128 * K;
 
-// pthread on Ubuntu is always in floating stack mode
-bool os::Linux::supports_variable_stack_size() {  return true; }
-
 // return default stack size for thr_type
 size_t os::Linux::default_stack_size(os::ThreadType thr_type) {
   // default stack size (compiler thread needs larger stack)
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -623,11 +623,6 @@
 size_t os::Linux::min_stack_allowed  =  (48 DEBUG_ONLY(+4))*K;
 #endif // AMD64
 
-// Test if pthread library can support variable thread stack size.
-bool os::Linux::supports_variable_stack_size() {
-  return true;
-}
-
 // return default stack size for thr_type
 size_t os::Linux::default_stack_size(os::ThreadType thr_type) {
   // default stack size (compiler thread needs larger stack)
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -305,10 +305,6 @@
 
 size_t os::Linux::min_stack_allowed = 64 * K;
 
-bool os::Linux::supports_variable_stack_size() {
-  return true;
-}
-
 size_t os::Linux::default_stack_size(os::ThreadType thr_type) {
 #ifdef _LP64
   size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -239,25 +239,6 @@
   return true;
 }
 
-bool Compiler::is_intrinsic_disabled_by_flag(methodHandle method) {
-  vmIntrinsics::ID id = method->intrinsic_id();
-  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
-
-  if (vmIntrinsics::is_disabled_by_flags(id)) {
-    return true;
-  }
-
-  if (!InlineNatives && id != vmIntrinsics::_Reference_get) {
-    return true;
-  }
-
-  if (!InlineClassNatives && id == vmIntrinsics::_getClass) {
-    return true;
-  }
-
-  return false;
-}
-
 void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
   BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
   assert(buffer_blob != NULL, "Must exist");
@@ -275,7 +256,3 @@
 void Compiler::print_timers() {
   Compilation::print_timers();
 }
-
-bool Compiler::is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
-  return is_intrinsic_supported(method) && !is_intrinsic_disabled_by_flag(method);
-}
--- a/hotspot/src/share/vm/c1/c1_Compiler.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -55,18 +55,9 @@
   // Print compilation timers and statistics
   virtual void print_timers();
 
-  // Check the availability of an intrinsic for 'method' given a compilation context.
-  // The compilation context is needed to support per-method usage of the
-  // DisableIntrinsic flag. However, as C1 ignores the DisableIntrinsic flag, it
-  // ignores the compilation context.
-  virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context);
-
   // Check if the C1 compiler supports an intrinsic for 'method'.
   virtual bool is_intrinsic_supported(methodHandle method);
 
-  // Processing of command-line flags specific to the C1 compiler.
-  virtual bool is_intrinsic_disabled_by_flag(methodHandle method);
-
   // Size of the code buffer
   static int code_buffer_size();
 };
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -3491,8 +3491,16 @@
 bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
   // For calling is_intrinsic_available we need to transition to
   // the '_thread_in_vm' state because is_intrinsic_available()
-  // does not accesses critical VM-internal data.
-  if (!_compilation->compiler()->is_intrinsic_available(callee->get_Method(), NULL)) {
+  // accesses critical VM-internal data.
+  bool is_available = false;
+  {
+    VM_ENTRY_MARK;
+    methodHandle mh(THREAD, callee->get_Method());
+    methodHandle ct(THREAD, method()->get_Method());
+    is_available = _compilation->compiler()->is_intrinsic_available(mh, ct);
+  }
+
+  if (!is_available) {
     if (!InlineNatives) {
       // Return false and also set message that the inlining of
       // intrinsics has been disabled in general.
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -443,6 +443,7 @@
 
   // emit the static call stub stuff out of line
   emit_static_call_stub();
+  CHECK_BAILOUT();
 
   switch (op->code()) {
   case lir_static_call:
--- a/hotspot/src/share/vm/classfile/imageDecompressor.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/classfile/imageDecompressor.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -22,8 +22,8 @@
  *
  */
 
+#include "precompiled.hpp"
 #include "runtime/thread.inline.hpp"
-#include "precompiled.hpp"
 #include "classfile/imageDecompressor.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/bytes.hpp"
--- a/hotspot/src/share/vm/classfile/imageDecompressor.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/classfile/imageDecompressor.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -26,7 +26,6 @@
 #define SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
 
 #include "runtime/thread.inline.hpp"
-#include "precompiled.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/imageFile.hpp"
 #include "classfile/symbolTable.hpp"
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -417,8 +417,59 @@
   }
 }
 
-bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
+bool vmIntrinsics::is_disabled_by_flags(methodHandle method, methodHandle compilation_context) {
+  vmIntrinsics::ID id = method->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
+
+  // Check if the intrinsic corresponding to 'method' has been disabled on
+  // the command line by using the DisableIntrinsic flag (either globally
+  // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
+  // for details).
+  // Usually, the compilation context is the caller of the method 'method'.
+  // The only case when for a non-recursive method 'method' the compilation context
+  // is not the caller of the 'method' (but it is the method itself) is
+  // java.lang.ref.Referene::get.
+  // For java.lang.ref.Reference::get, the intrinsic version is used
+  // instead of the compiled version so that the value in the referent
+  // field can be registered by the G1 pre-barrier code. The intrinsified
+  // version of Reference::get also adds a memory barrier to prevent
+  // commoning reads from the referent field across safepoint since GC
+  // can change the referent field's value. See Compile::Compile()
+  // in src/share/vm/opto/compile.cpp or
+  // GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
+  // for more details.
+  ccstr disable_intr = NULL;
+  if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
+      (!compilation_context.is_null() &&
+       CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
+       strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
+  ) {
+    return true;
+  }
+
+  // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
+  // the following switch statement.
+  if (!InlineNatives) {
+    switch (id) {
+    case vmIntrinsics::_indexOf:
+    case vmIntrinsics::_compareTo:
+    case vmIntrinsics::_equals:
+    case vmIntrinsics::_equalsC:
+    case vmIntrinsics::_getAndAddInt:
+    case vmIntrinsics::_getAndAddLong:
+    case vmIntrinsics::_getAndSetInt:
+    case vmIntrinsics::_getAndSetLong:
+    case vmIntrinsics::_getAndSetObject:
+    case vmIntrinsics::_loadFence:
+    case vmIntrinsics::_storeFence:
+    case vmIntrinsics::_fullFence:
+    case vmIntrinsics::_Reference_get:
+      break;
+    default:
+      return true;
+    }
+  }
+
   switch (id) {
   case vmIntrinsics::_isInstance:
   case vmIntrinsics::_isAssignableFrom:
@@ -430,6 +481,7 @@
   case vmIntrinsics::_Class_cast:
   case vmIntrinsics::_getLength:
   case vmIntrinsics::_newArray:
+  case vmIntrinsics::_getClass:
     if (!InlineClassNatives) return true;
     break;
   case vmIntrinsics::_currentThread:
@@ -522,6 +574,12 @@
   case vmIntrinsics::_getAndSetInt:
   case vmIntrinsics::_getAndSetLong:
   case vmIntrinsics::_getAndSetObject:
+  case vmIntrinsics::_loadFence:
+  case vmIntrinsics::_storeFence:
+  case vmIntrinsics::_fullFence:
+  case vmIntrinsics::_compareAndSwapObject:
+  case vmIntrinsics::_compareAndSwapLong:
+  case vmIntrinsics::_compareAndSwapInt:
     if (!InlineUnsafeOps) return true;
     break;
   case vmIntrinsics::_getShortUnaligned:
@@ -584,8 +642,8 @@
     if (!InlineObjectCopy || !InlineArrayCopy) return true;
     break;
   case vmIntrinsics::_compareTo:
-     if (!SpecialStringCompareTo) return true;
-     break;
+    if (!SpecialStringCompareTo) return true;
+    break;
   case vmIntrinsics::_indexOf:
     if (!SpecialStringIndexOf) return true;
     break;
@@ -602,8 +660,8 @@
     if (!InlineReflectionGetCallerClass) return true;
     break;
   case vmIntrinsics::_multiplyToLen:
-      if (!UseMultiplyToLenIntrinsic) return true;
-      break;
+    if (!UseMultiplyToLenIntrinsic) return true;
+    break;
   case vmIntrinsics::_squareToLen:
     if (!UseSquareToLenIntrinsic) return true;
     break;
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -568,6 +568,11 @@
   template(java_lang_management_ThreadInfo_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;)V") \
   template(java_lang_management_ThreadInfo_with_locks_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;[Ljava/lang/Object;[I[Ljava/lang/Object;)V") \
   template(long_long_long_long_void_signature,         "(JJJJ)V")                                                 \
+  template(finalizer_histogram_klass,                  "java/lang/ref/FinalizerHistogram")                        \
+  template(void_finalizer_histogram_entry_array_signature,  "()[Ljava/lang/ref/FinalizerHistogram$Entry;")                        \
+  template(get_finalizer_histogram_name,               "getFinalizerHistogram")                                   \
+  template(finalizer_histogram_entry_name_field,       "className")                                               \
+  template(finalizer_histogram_entry_count_field,      "instanceCount")                                           \
                                                                                                                   \
   template(java_lang_management_MemoryPoolMXBean,      "java/lang/management/MemoryPoolMXBean")                   \
   template(java_lang_management_MemoryManagerMXBean,   "java/lang/management/MemoryManagerMXBean")                \
@@ -1384,10 +1389,9 @@
   // 'method' requires predicated logic.
   static int predicates_needed(vmIntrinsics::ID id);
 
-  // Returns true if an intrinsic is disabled by command-line flags and
-  // false otherwise. Implements functionality common to the C1
-  // and the C2 compiler.
-  static bool is_disabled_by_flags(vmIntrinsics::ID id);
+  // Returns true if a compiler intrinsic is disabled by command-line flags
+  // and false otherwise.
+  static bool is_disabled_by_flags(methodHandle method, methodHandle compilation_context);
 };
 
 #endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
--- a/hotspot/src/share/vm/code/compiledIC.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/code/compiledIC.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -306,7 +306,7 @@
   friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site);
 
   // Code
-  static void emit_to_interp_stub(CodeBuffer &cbuf);
+  static address emit_to_interp_stub(CodeBuffer &cbuf);
   static int to_interp_stub_size();
   static int reloc_to_interp_stub();
 
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -75,8 +75,8 @@
   //
   // The second parameter, 'compilation_context', is needed to implement functionality
   // related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can
-  // be used to prohibit the C2 compiler (but not the C1 compiler) to use an intrinsic.
-  // There are three ways to disable an intrinsic using the DisableIntrinsic flag:
+  // be used to prohibit the compilers to use an intrinsic. There are three ways to
+  // disable an intrinsic using the DisableIntrinsic flag:
   //
   // (1) -XX:DisableIntrinsic=_hashCode,_getClass
   //     Disables intrinsification of _hashCode and _getClass globally
@@ -96,7 +96,8 @@
   // compilation context is aClass::aMethod and java.lang.ref.Reference::get,
   // respectively.
   virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
-    return false;
+    return is_intrinsic_supported(method) &&
+           !vmIntrinsics::is_disabled_by_flags(method, compilation_context);
   }
 
   // Determines if an intrinsic is supported by the compiler, that is,
@@ -111,13 +112,6 @@
     return false;
   }
 
-  // Implements compiler-specific processing of command-line flags.
-  // Processing of command-line flags common to all compilers is implemented
-  // in vmIntrinsicss::is_disabled_by_flag.
-  virtual bool is_intrinsic_disabled_by_flag(methodHandle method) {
-    return false;
-  }
-
   // Compiler type queries.
   bool is_c1()                                   { return _type == c1; }
   bool is_c2()                                   { return _type == c2; }
--- a/hotspot/src/share/vm/opto/arraycopynode.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/arraycopynode.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -79,10 +79,15 @@
 
 #ifndef PRODUCT
 const char* ArrayCopyNode::_kind_names[] = {"arraycopy", "arraycopy, validated arguments", "clone", "oop array clone", "CopyOf", "CopyOfRange"};
+
 void ArrayCopyNode::dump_spec(outputStream *st) const {
   CallNode::dump_spec(st);
   st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : "");
 }
+
+void ArrayCopyNode::dump_compact_spec(outputStream* st) const {
+  st->print("%s%s", _kind_names[_kind], _alloc_tightly_coupled ? ",tight" : "");
+}
 #endif
 
 intptr_t ArrayCopyNode::get_length_if_constant(PhaseGVN *phase) const {
--- a/hotspot/src/share/vm/opto/arraycopynode.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/arraycopynode.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -164,6 +164,7 @@
 
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
+  virtual void dump_compact_spec(outputStream* st) const;
 #endif
 };
 #endif // SHARE_VM_OPTO_ARRAYCOPYNODE_HPP
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -623,9 +623,6 @@
   diagnostic(bool, PrintIntrinsics, false,                                  \
           "prints attempted and successful inlining of intrinsics")         \
                                                                             \
-  diagnostic(ccstrlist, DisableIntrinsic, "",                               \
-          "do not expand intrinsics whose (internal) names appear here")    \
-                                                                            \
   develop(bool, StressReflectiveCode, false,                                \
           "Use inexact types at allocations, etc., to test reflection")     \
                                                                             \
--- a/hotspot/src/share/vm/opto/c2compiler.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -157,14 +157,6 @@
   Compile::print_timers();
 }
 
-bool C2Compiler::is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
-  // Assume a non-virtual dispatch. A virtual dispatch is
-  // possible for only a limited set of available intrinsics whereas
-  // a non-virtual dispatch is possible for all available intrinsics.
-  return is_intrinsic_supported(method, false) &&
-         !is_intrinsic_disabled_by_flag(method, compilation_context);
-}
-
 bool C2Compiler::is_intrinsic_supported(methodHandle method, bool is_virtual) {
   vmIntrinsics::ID id = method->intrinsic_id();
   assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
@@ -436,78 +428,6 @@
   return true;
 }
 
-bool C2Compiler::is_intrinsic_disabled_by_flag(methodHandle method, methodHandle compilation_context) {
-  vmIntrinsics::ID id = method->intrinsic_id();
-  assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
-
-  if (vmIntrinsics::is_disabled_by_flags(method->intrinsic_id())) {
-    return true;
-  }
-
-  // Check if the intrinsic corresponding to 'method' has been disabled on
-  // the command line by using the DisableIntrinsic flag (either globally
-  // or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
-  // for details).
-  // Usually, the compilation context is the caller of the method 'method'.
-  // The only case when for a non-recursive method 'method' the compilation context
-  // is not the caller of the 'method' (but it is the method itself) is
-  // java.lang.ref.Referene::get.
-  // For java.lang.ref.Reference::get, the intrinsic version is used
-  // instead of the C2-compiled version so that the value in the referent
-  // field can be registered by the G1 pre-barrier code. The intrinsified
-  // version of Reference::get also adds a memory barrier to prevent
-  // commoning reads from the referent field across safepoint since GC
-  // can change the referent field's value. See Compile::Compile()
-  // in src/share/vm/opto/compile.cpp for more details.
-  ccstr disable_intr = NULL;
-  if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
-      (!compilation_context.is_null() &&
-       CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
-       strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
-  ) {
-    return true;
-  }
-
-  // -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
-  // the following switch statement.
-  if (!InlineNatives) {
-    switch (id) {
-    case vmIntrinsics::_indexOf:
-    case vmIntrinsics::_compareTo:
-    case vmIntrinsics::_equals:
-    case vmIntrinsics::_equalsC:
-    case vmIntrinsics::_getAndAddInt:
-    case vmIntrinsics::_getAndAddLong:
-    case vmIntrinsics::_getAndSetInt:
-    case vmIntrinsics::_getAndSetLong:
-    case vmIntrinsics::_getAndSetObject:
-    case vmIntrinsics::_loadFence:
-    case vmIntrinsics::_storeFence:
-    case vmIntrinsics::_fullFence:
-    case vmIntrinsics::_Reference_get:
-      break;
-    default:
-      return true;
-    }
-  }
-
-  if (!InlineUnsafeOps) {
-    switch (id) {
-    case vmIntrinsics::_loadFence:
-    case vmIntrinsics::_storeFence:
-    case vmIntrinsics::_fullFence:
-    case vmIntrinsics::_compareAndSwapObject:
-    case vmIntrinsics::_compareAndSwapLong:
-    case vmIntrinsics::_compareAndSwapInt:
-      return true;
-    default:
-      return false;
-    }
-  }
-
-  return false;
-}
-
 int C2Compiler::initial_code_buffer_size() {
   assert(SegmentedCodeCache, "Should be only used with a segmented code cache");
   return Compile::MAX_inst_size + Compile::MAX_locs_size + initial_const_capacity;
--- a/hotspot/src/share/vm/opto/c2compiler.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/c2compiler.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -51,11 +51,11 @@
   // Print compilation timers and statistics
   void print_timers();
 
-  // Check the availability of an intrinsic for 'method' given a compilation context.
-  virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context);
-
   // Return true if the intrinsification of a method supported by the compiler
-  // assuming a non-virtual dispatch. Return false otherwise.
+  // assuming a non-virtual dispatch. (A virtual dispatch is
+  // possible for only a limited set of available intrinsics whereas
+  // a non-virtual dispatch is possible for all available intrinsics.)
+  // Return false otherwise.
   virtual bool is_intrinsic_supported(methodHandle method) {
     return is_intrinsic_supported(method, false);
   }
@@ -64,13 +64,6 @@
   // the dispatch mode specified by the 'is_virtual' parameter.
   virtual bool is_intrinsic_supported(methodHandle method, bool is_virtual);
 
-  // Processing of command-line flags specific to the C2 compiler.
-  virtual bool is_intrinsic_disabled_by_flag(methodHandle method) {
-    return is_intrinsic_disabled_by_flag(method, NULL);
-  }
-
-  virtual bool is_intrinsic_disabled_by_flag(methodHandle method, methodHandle compilation_context);
-
   // Initial size of the code buffer (may be increased at runtime)
   static int initial_code_buffer_size();
 };
--- a/hotspot/src/share/vm/opto/callnode.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -52,6 +52,7 @@
 const Type *StartNode::Value(PhaseTransform *phase) const { return _domain; }
 #ifndef PRODUCT
 void StartNode::dump_spec(outputStream *st) const { st->print(" #"); _domain->dump_on(st);}
+void StartNode::dump_compact_spec(outputStream *st) const { /* empty */ }
 #endif
 
 //------------------------------Ideal------------------------------------------
@@ -121,6 +122,23 @@
     if( !Verbose && !WizardMode )   bottom_type()->dump_on(st);
   }
 }
+
+void ParmNode::dump_compact_spec(outputStream *st) const {
+  if (_con < TypeFunc::Parms) {
+    st->print("%s", names[_con]);
+  } else {
+    st->print("%d:", _con-TypeFunc::Parms);
+    // unconditionally dump bottom_type
+    bottom_type()->dump_on(st);
+  }
+}
+
+// For a ParmNode, all immediate inputs and outputs are considered relevant
+// both in compact and standard representation.
+void ParmNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  this->collect_nodes(in_rel, 1, false, false);
+  this->collect_nodes(out_rel, -1, false, false);
+}
 #endif
 
 uint ParmNode::ideal_reg() const {
@@ -948,6 +966,14 @@
   if( _method ) _method->print_short_name(st);
   CallNode::dump_spec(st);
 }
+
+void CallJavaNode::dump_compact_spec(outputStream* st) const {
+  if (_method) {
+    _method->print_short_name(st);
+  } else {
+    st->print("<?>");
+  }
+}
 #endif
 
 //=============================================================================
@@ -995,6 +1021,16 @@
   }
   CallJavaNode::dump_spec(st);
 }
+
+void CallStaticJavaNode::dump_compact_spec(outputStream* st) const {
+  if (_method) {
+    _method->print_short_name(st);
+  } else if (_name) {
+    st->print("%s", _name);
+  } else {
+    st->print("<?>");
+  }
+}
 #endif
 
 //=============================================================================
@@ -1130,6 +1166,19 @@
   st->print(" SafePoint ");
   _replaced_nodes.dump(st);
 }
+
+// The related nodes of a SafepointNode are all data inputs, excluding the
+// control boundary, as well as all outputs till level 2 (to include projection
+// nodes and targets). In compact mode, just include inputs till level 1 and
+// outputs as before.
+void SafePointNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  if (compact) {
+    this->collect_nodes(in_rel, 1, false, false);
+  } else {
+    this->collect_nodes_in_all_data(in_rel, false);
+  }
+  this->collect_nodes(out_rel, -2, false, false);
+}
 #endif
 
 const RegMask &SafePointNode::in_RegMask(uint idx) const {
@@ -1676,6 +1725,27 @@
     _counter->set_tag(NamedCounter::EliminatedLockCounter);
   }
 }
+
+const char* AbstractLockNode::_kind_names[] = {"Regular", "NonEscObj", "Coarsened", "Nested"};
+
+void AbstractLockNode::dump_spec(outputStream* st) const {
+  st->print("%s ", _kind_names[_kind]);
+  CallNode::dump_spec(st);
+}
+
+void AbstractLockNode::dump_compact_spec(outputStream* st) const {
+  st->print("%s", _kind_names[_kind]);
+}
+
+// The related set of lock nodes includes the control boundary.
+void AbstractLockNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  if (compact) {
+      this->collect_nodes(in_rel, 1, false, false);
+    } else {
+      this->collect_nodes_in_all_data(in_rel, true);
+    }
+    this->collect_nodes(out_rel, -2, false, false);
+}
 #endif
 
 //=============================================================================
--- a/hotspot/src/share/vm/opto/callnode.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/callnode.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -84,6 +84,7 @@
   virtual uint ideal_reg() const { return 0; }
 #ifndef PRODUCT
   virtual void  dump_spec(outputStream *st) const;
+  virtual void  dump_compact_spec(outputStream *st) const;
 #endif
 };
 
@@ -110,6 +111,8 @@
   virtual uint ideal_reg() const;
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
+  virtual void dump_compact_spec(outputStream *st) const;
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
 #endif
 };
 
@@ -476,6 +479,7 @@
 
 #ifndef PRODUCT
   virtual void           dump_spec(outputStream *st) const;
+  virtual void           related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
 #endif
 };
 
@@ -675,6 +679,7 @@
 
 #ifndef PRODUCT
   virtual void  dump_spec(outputStream *st) const;
+  virtual void  dump_compact_spec(outputStream *st) const;
 #endif
 };
 
@@ -730,6 +735,7 @@
   virtual int         Opcode() const;
 #ifndef PRODUCT
   virtual void        dump_spec(outputStream *st) const;
+  virtual void        dump_compact_spec(outputStream *st) const;
 #endif
 };
 
@@ -951,6 +957,7 @@
   } _kind;
 #ifndef PRODUCT
   NamedCounter* _counter;
+  static const char* _kind_names[Nested+1];
 #endif
 
 protected:
@@ -1005,6 +1012,9 @@
 #ifndef PRODUCT
   void create_lock_counter(JVMState* s);
   NamedCounter* counter() const { return _counter; }
+  virtual void dump_spec(outputStream* st) const;
+  virtual void dump_compact_spec(outputStream* st) const;
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
 #endif
 };
 
--- a/hotspot/src/share/vm/opto/cfgnode.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -2023,6 +2023,14 @@
 }
 
 #ifndef PRODUCT
+void PhiNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  // For a PhiNode, the set of related nodes includes all inputs till level 2,
+  // and all outputs till level 1. In compact mode, inputs till level 1 are
+  // collected.
+  this->collect_nodes(in_rel, compact ? 1 : 2, false, false);
+  this->collect_nodes(out_rel, -1, false, false);
+}
+
 void PhiNode::dump_spec(outputStream *st) const {
   TypeNode::dump_spec(st);
   if (is_tripcount()) {
@@ -2047,11 +2055,33 @@
   return RegMask::Empty;
 }
 
+#ifndef PRODUCT
+//-----------------------------related-----------------------------------------
+// The related nodes of a GotoNode are all inputs at level 1, as well as the
+// outputs at level 1. This is regardless of compact mode.
+void GotoNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  this->collect_nodes(in_rel, 1, false, false);
+  this->collect_nodes(out_rel, -1, false, false);
+}
+#endif
+
+
 //=============================================================================
 const RegMask &JumpNode::out_RegMask() const {
   return RegMask::Empty;
 }
 
+#ifndef PRODUCT
+//-----------------------------related-----------------------------------------
+// The related nodes of a JumpNode are all inputs at level 1, as well as the
+// outputs at level 2 (to include actual jump targets beyond projection nodes).
+// This is regardless of compact mode.
+void JumpNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  this->collect_nodes(in_rel, 1, false, false);
+  this->collect_nodes(out_rel, -2, false, false);
+}
+#endif
+
 //=============================================================================
 const RegMask &JProjNode::out_RegMask() const {
   return RegMask::Empty;
@@ -2105,7 +2135,18 @@
 #ifndef PRODUCT
 void JumpProjNode::dump_spec(outputStream *st) const {
   ProjNode::dump_spec(st);
-   st->print("@bci %d ",_dest_bci);
+  st->print("@bci %d ",_dest_bci);
+}
+
+void JumpProjNode::dump_compact_spec(outputStream *st) const {
+  ProjNode::dump_compact_spec(st);
+  st->print("(%d)%d@%d", _switch_val, _proj_no, _dest_bci);
+}
+
+void JumpProjNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  // The related nodes of a JumpProjNode are its inputs and outputs at level 1.
+  this->collect_nodes(in_rel, 1, false, false);
+  this->collect_nodes(out_rel, -1, false, false);
 }
 #endif
 
--- a/hotspot/src/share/vm/opto/cfgnode.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/cfgnode.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -204,6 +204,7 @@
   virtual const RegMask &out_RegMask() const;
   virtual const RegMask &in_RegMask(uint) const;
 #ifndef PRODUCT
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
   virtual void dump_spec(outputStream *st) const;
 #endif
 #ifdef ASSERT
@@ -229,6 +230,10 @@
   virtual const Type *Value( PhaseTransform *phase ) const;
   virtual Node *Identity( PhaseTransform *phase );
   virtual const RegMask &out_RegMask() const;
+
+#ifndef PRODUCT
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
+#endif
 };
 
 //------------------------------CProjNode--------------------------------------
@@ -382,6 +387,7 @@
 
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
+  virtual void related(GrowableArray <Node *> *in_rel, GrowableArray <Node *> *out_rel, bool compact) const;
 #endif
 };
 
@@ -393,6 +399,11 @@
 protected:
   // Type of If input when this branch is always taken
   virtual bool always_taken(const TypeTuple* t) const = 0;
+
+#ifndef PRODUCT
+public:
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
+#endif
 };
 
 class IfTrueNode : public IfProjNode {
@@ -455,6 +466,9 @@
   virtual int   Opcode() const;
   virtual const RegMask& out_RegMask() const;
   virtual const Node* is_block_proj() const { return this; }
+#ifndef PRODUCT
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
+#endif
 };
 
 class JumpProjNode : public JProjNode {
@@ -479,6 +493,8 @@
   uint proj_no()     const { return _proj_no; }
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
+  virtual void dump_compact_spec(outputStream *st) const;
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
 #endif
 };
 
--- a/hotspot/src/share/vm/opto/compile.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -594,6 +594,10 @@
     n->as_MachBranch()->label_set(&fakeL, 0);
   }
   n->emit(buf, this->regalloc());
+
+  // Emitting into the scratch buffer should not fail
+  assert (!failing(), err_msg_res("Must not have pending failure. Reason is: %s", failure_reason()));
+
   if (is_branch) // Restore label.
     n->as_MachBranch()->label_set(saveL, save_bnum);
 
--- a/hotspot/src/share/vm/opto/ifnode.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/ifnode.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1601,11 +1601,41 @@
   return this;
 }
 
+#ifndef PRODUCT
+//-------------------------------related---------------------------------------
+// An IfProjNode's related node set consists of its input (an IfNode) including
+// the IfNode's condition, plus all of its outputs at level 1. In compact mode,
+// the restrictions for IfNode apply (see IfNode::rel).
+void IfProjNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  Node* ifNode = this->in(0);
+  in_rel->append(ifNode);
+  if (compact) {
+    ifNode->collect_nodes(in_rel, 3, false, true);
+  } else {
+    ifNode->collect_nodes_in_all_data(in_rel, false);
+  }
+  this->collect_nodes(out_rel, -1, false, false);
+}
+
 //------------------------------dump_spec--------------------------------------
-#ifndef PRODUCT
 void IfNode::dump_spec(outputStream *st) const {
   st->print("P=%f, C=%f",_prob,_fcnt);
 }
+
+//-------------------------------related---------------------------------------
+// For an IfNode, the set of related output nodes is just the output nodes till
+// depth 2, i.e, the IfTrue/IfFalse projection nodes plus the nodes they refer.
+// The related input nodes contain no control nodes, but all data nodes
+// pertaining to the condition. In compact mode, the input nodes are collected
+// up to a depth of 3.
+void IfNode::related(GrowableArray <Node *> *in_rel, GrowableArray <Node *> *out_rel, bool compact) const {
+  if (compact) {
+    this->collect_nodes(in_rel, 3, false, true);
+  } else {
+    this->collect_nodes_in_all_data(in_rel, false);
+  }
+  this->collect_nodes(out_rel, -2, false, false);
+}
 #endif
 
 //------------------------------idealize_test----------------------------------
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -327,7 +327,7 @@
     methodHandle mh(THREAD, m->get_Method());
     methodHandle ct(THREAD, method()->get_Method());
     is_available = compiler->is_intrinsic_supported(mh, is_virtual) &&
-                   !compiler->is_intrinsic_disabled_by_flag(mh, ct);
+                   !vmIntrinsics::is_disabled_by_flags(mh, ct);
   }
 
   if (is_available) {
--- a/hotspot/src/share/vm/opto/movenode.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/movenode.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -396,3 +396,17 @@
   return TypeLong::make( v.get_jlong() );
 }
 
+#ifndef PRODUCT
+//----------------------------BinaryNode---------------------------------------
+// The set of related nodes for a BinaryNode is all data inputs and all outputs
+// till level 2 (i.e., one beyond the associated CMoveNode). In compact mode,
+// it's the inputs till level 1 and the outputs till level 2.
+void BinaryNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  if (compact) {
+    this->collect_nodes(in_rel, 1, false, true);
+  } else {
+    this->collect_nodes_in_all_data(in_rel, false);
+  }
+  this->collect_nodes(out_rel, -2, false, false);
+}
+#endif
--- a/hotspot/src/share/vm/opto/movenode.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/movenode.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -145,6 +145,10 @@
   BinaryNode( Node *n1, Node *n2 ) : Node(0,n1,n2) { }
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return 0; }
+
+#ifndef PRODUCT
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
+#endif
 };
 
 
--- a/hotspot/src/share/vm/opto/multnode.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/multnode.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -118,6 +118,20 @@
 bool ProjNode::pinned() const { return in(0)->pinned(); }
 #ifndef PRODUCT
 void ProjNode::dump_spec(outputStream *st) const { st->print("#%d",_con); if(_is_io_use) st->print(" (i_o_use)");}
+
+void ProjNode::dump_compact_spec(outputStream *st) const {
+  for (DUIterator i = this->outs(); this->has_out(i); i++) {
+    Node* o = this->out(i);
+    if (NotANode(o)) {
+      st->print("[?]");
+    } else if (o == NULL) {
+      st->print("[_]");
+    } else {
+      st->print("[%d]", o->_idx);
+    }
+  }
+  st->print("#%d", _con);
+}
 #endif
 
 //----------------------------check_con----------------------------------------
--- a/hotspot/src/share/vm/opto/multnode.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/multnode.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,7 @@
 
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
+  virtual void dump_compact_spec(outputStream *st) const;
 #endif
 
   // Return uncommon trap call node if proj is for "proj->[region->..]call_uct"
--- a/hotspot/src/share/vm/opto/node.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/node.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1489,16 +1489,6 @@
 
 #ifndef PRODUCT
 
-//----------------------------NotANode----------------------------------------
-// Used in debugging code to avoid walking across dead or uninitialized edges.
-static inline bool NotANode(const Node* n) {
-  if (n == NULL)                   return true;
-  if (((intptr_t)n & 1) != 0)      return true;  // uninitialized, etc.
-  if (*(address*)n == badAddress)  return true;  // kill by Node::destruct
-  return false;
-}
-
-
 //------------------------------find------------------------------------------
 // Find a neighbor of this Node with the given _idx
 // If idx is negative, find its absolute value, following both _in and _out.
@@ -1636,11 +1626,11 @@
 
 //------------------------------dump------------------------------------------
 // Dump a Node
-void Node::dump(const char* suffix, outputStream *st) const {
+void Node::dump(const char* suffix, bool mark, outputStream *st) const {
   Compile* C = Compile::current();
   bool is_new = C->node_arena()->contains(this);
   C->_in_dump_cnt++;
-  st->print("%c%d\t%s\t=== ", is_new ? ' ' : 'o', _idx, Name());
+  st->print("%c%d%s\t%s\t=== ", is_new ? ' ' : 'o', _idx, mark ? " >" : "", Name());
 
   // Dump the required and precedence inputs
   dump_req(st);
@@ -1760,42 +1750,60 @@
   st->print("]] ");
 }
 
-//------------------------------dump_nodes-------------------------------------
-static void dump_nodes(const Node* start, int d, bool only_ctrl) {
-  Node* s = (Node*)start; // remove const
-  if (NotANode(s)) return;
-
-  uint depth = (uint)ABS(d);
-  int direction = d;
-  Compile* C = Compile::current();
-  GrowableArray <Node *> nstack(C->unique());
-
-  nstack.append(s);
+//----------------------------collect_nodes_i----------------------------------
+// Collects nodes from an Ideal graph, starting from a given start node and
+// moving in a given direction until a certain depth (distance from the start
+// node) is reached. Duplicates are ignored.
+// Arguments:
+//   nstack:        the nodes are collected into this array.
+//   start:         the node at which to start collecting.
+//   direction:     if this is a positive number, collect input nodes; if it is
+//                  a negative number, collect output nodes.
+//   depth:         collect nodes up to this distance from the start node.
+//   include_start: whether to include the start node in the result collection.
+//   only_ctrl:     whether to regard control edges only during traversal.
+//   only_data:     whether to regard data edges only during traversal.
+static void collect_nodes_i(GrowableArray<Node*> *nstack, const Node* start, int direction, uint depth, bool include_start, bool only_ctrl, bool only_data) {
+  Node* s = (Node*) start; // remove const
+  nstack->append(s);
   int begin = 0;
   int end = 0;
   for(uint i = 0; i < depth; i++) {
-    end = nstack.length();
+    end = nstack->length();
     for(int j = begin; j < end; j++) {
-      Node* tp  = nstack.at(j);
+      Node* tp  = nstack->at(j);
       uint limit = direction > 0 ? tp->len() : tp->outcnt();
       for(uint k = 0; k < limit; k++) {
         Node* n = direction > 0 ? tp->in(k) : tp->raw_out(k);
 
         if (NotANode(n))  continue;
         // do not recurse through top or the root (would reach unrelated stuff)
-        if (n->is_Root() || n->is_top())  continue;
+        if (n->is_Root() || n->is_top()) continue;
         if (only_ctrl && !n->is_CFG()) continue;
+        if (only_data && n->is_CFG()) continue;
 
-        bool on_stack = nstack.contains(n);
+        bool on_stack = nstack->contains(n);
         if (!on_stack) {
-          nstack.append(n);
+          nstack->append(n);
         }
       }
     }
     begin = end;
   }
-  end = nstack.length();
-  if (direction > 0) {
+  if (!include_start) {
+    nstack->remove(s);
+  }
+}
+
+//------------------------------dump_nodes-------------------------------------
+static void dump_nodes(const Node* start, int d, bool only_ctrl) {
+  if (NotANode(start)) return;
+
+  GrowableArray <Node *> nstack(Compile::current()->unique());
+  collect_nodes_i(&nstack, start, d, (uint) ABS(d), true, only_ctrl, false);
+
+  int end = nstack.length();
+  if (d > 0) {
     for(int j = end-1; j >= 0; j--) {
       nstack.at(j)->dump();
     }
@@ -1817,6 +1825,221 @@
   dump_nodes(this, d, true);
 }
 
+//-----------------------------dump_compact------------------------------------
+void Node::dump_comp() const {
+  this->dump_comp("\n");
+}
+
+//-----------------------------dump_compact------------------------------------
+// Dump a Node in compact representation, i.e., just print its name and index.
+// Nodes can specify additional specifics to print in compact representation by
+// implementing dump_compact_spec.
+void Node::dump_comp(const char* suffix, outputStream *st) const {
+  Compile* C = Compile::current();
+  C->_in_dump_cnt++;
+  st->print("%s(%d)", Name(), _idx);
+  this->dump_compact_spec(st);
+  if (suffix) {
+    st->print("%s", suffix);
+  }
+  C->_in_dump_cnt--;
+}
+
+//----------------------------dump_related-------------------------------------
+// Dump a Node's related nodes - the notion of "related" depends on the Node at
+// hand and is determined by the implementation of the virtual method rel.
+void Node::dump_related() const {
+  Compile* C = Compile::current();
+  GrowableArray <Node *> in_rel(C->unique());
+  GrowableArray <Node *> out_rel(C->unique());
+  this->related(&in_rel, &out_rel, false);
+  for (int i = in_rel.length() - 1; i >= 0; i--) {
+    in_rel.at(i)->dump();
+  }
+  this->dump("\n", true);
+  for (int i = 0; i < out_rel.length(); i++) {
+    out_rel.at(i)->dump();
+  }
+}
+
+//----------------------------dump_related-------------------------------------
+// Dump a Node's related nodes up to a given depth (distance from the start
+// node).
+// Arguments:
+//   d_in:  depth for input nodes.
+//   d_out: depth for output nodes (note: this also is a positive number).
+void Node::dump_related(uint d_in, uint d_out) const {
+  Compile* C = Compile::current();
+  GrowableArray <Node *> in_rel(C->unique());
+  GrowableArray <Node *> out_rel(C->unique());
+
+  // call collect_nodes_i directly
+  collect_nodes_i(&in_rel, this, 1, d_in, false, false, false);
+  collect_nodes_i(&out_rel, this, -1, d_out, false, false, false);
+
+  for (int i = in_rel.length() - 1; i >= 0; i--) {
+    in_rel.at(i)->dump();
+  }
+  this->dump("\n", true);
+  for (int i = 0; i < out_rel.length(); i++) {
+    out_rel.at(i)->dump();
+  }
+}
+
+//------------------------dump_related_compact---------------------------------
+// Dump a Node's related nodes in compact representation. The notion of
+// "related" depends on the Node at hand and is determined by the implementation
+// of the virtual method rel.
+void Node::dump_related_compact() const {
+  Compile* C = Compile::current();
+  GrowableArray <Node *> in_rel(C->unique());
+  GrowableArray <Node *> out_rel(C->unique());
+  this->related(&in_rel, &out_rel, true);
+  int n_in = in_rel.length();
+  int n_out = out_rel.length();
+
+  this->dump_comp(n_in == 0 ? "\n" : "  ");
+  for (int i = 0; i < n_in; i++) {
+    in_rel.at(i)->dump_comp(i == n_in - 1 ? "\n" : "  ");
+  }
+  for (int i = 0; i < n_out; i++) {
+    out_rel.at(i)->dump_comp(i == n_out - 1 ? "\n" : "  ");
+  }
+}
+
+//------------------------------related----------------------------------------
+// Collect a Node's related nodes. The default behaviour just collects the
+// inputs and outputs at depth 1, including both control and data flow edges,
+// regardless of whether the presentation is compact or not. For data nodes,
+// the default is to collect all data inputs (till level 1 if compact), and
+// outputs till level 1.
+void Node::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  if (this->is_CFG()) {
+    collect_nodes_i(in_rel, this, 1, 1, false, false, false);
+    collect_nodes_i(out_rel, this, -1, 1, false, false, false);
+  } else {
+    if (compact) {
+      this->collect_nodes(in_rel, 1, false, true);
+    } else {
+      this->collect_nodes_in_all_data(in_rel, false);
+    }
+    this->collect_nodes(out_rel, -1, false, false);
+  }
+}
+
+//---------------------------collect_nodes-------------------------------------
+// An entry point to the low-level node collection facility, to start from a
+// given node in the graph. The start node is by default not included in the
+// result.
+// Arguments:
+//   ns:   collect the nodes into this data structure.
+//   d:    the depth (distance from start node) to which nodes should be
+//         collected. A value >0 indicates input nodes, a value <0, output
+//         nodes.
+//   ctrl: include only control nodes.
+//   data: include only data nodes.
+void Node::collect_nodes(GrowableArray<Node*> *ns, int d, bool ctrl, bool data) const {
+  if (ctrl && data) {
+    // ignore nonsensical combination
+    return;
+  }
+  collect_nodes_i(ns, this, d, (uint) ABS(d), false, ctrl, data);
+}
+
+//--------------------------collect_nodes_in-----------------------------------
+static void collect_nodes_in(Node* start, GrowableArray<Node*> *ns, bool primary_is_data, bool collect_secondary) {
+  // The maximum depth is determined using a BFS that visits all primary (data
+  // or control) inputs and increments the depth at each level.
+  uint d_in = 0;
+  GrowableArray<Node*> nodes(Compile::current()->unique());
+  nodes.push(start);
+  int nodes_at_current_level = 1;
+  int n_idx = 0;
+  while (nodes_at_current_level > 0) {
+    // Add all primary inputs reachable from the current level to the list, and
+    // increase the depth if there were any.
+    int nodes_at_next_level = 0;
+    bool nodes_added = false;
+    while (nodes_at_current_level > 0) {
+      nodes_at_current_level--;
+      Node* current = nodes.at(n_idx++);
+      for (uint i = 0; i < current->len(); i++) {
+        Node* n = current->in(i);
+        if (NotANode(n)) {
+          continue;
+        }
+        if ((primary_is_data && n->is_CFG()) || (!primary_is_data && !n->is_CFG())) {
+          continue;
+        }
+        if (!nodes.contains(n)) {
+          nodes.push(n);
+          nodes_added = true;
+          nodes_at_next_level++;
+        }
+      }
+    }
+    if (nodes_added) {
+      d_in++;
+    }
+    nodes_at_current_level = nodes_at_next_level;
+  }
+  start->collect_nodes(ns, d_in, !primary_is_data, primary_is_data);
+  if (collect_secondary) {
+    // Now, iterate over the secondary nodes in ns and add the respective
+    // boundary reachable from them.
+    GrowableArray<Node*> sns(Compile::current()->unique());
+    for (GrowableArrayIterator<Node*> it = ns->begin(); it != ns->end(); ++it) {
+      Node* n = *it;
+      n->collect_nodes(&sns, 1, primary_is_data, !primary_is_data);
+      for (GrowableArrayIterator<Node*> d = sns.begin(); d != sns.end(); ++d) {
+        ns->append_if_missing(*d);
+      }
+      sns.clear();
+    }
+  }
+}
+
+//---------------------collect_nodes_in_all_data-------------------------------
+// Collect the entire data input graph. Include the control boundary if
+// requested.
+// Arguments:
+//   ns:   collect the nodes into this data structure.
+//   ctrl: if true, include the control boundary.
+void Node::collect_nodes_in_all_data(GrowableArray<Node*> *ns, bool ctrl) const {
+  collect_nodes_in((Node*) this, ns, true, ctrl);
+}
+
+//--------------------------collect_nodes_in_all_ctrl--------------------------
+// Collect the entire control input graph. Include the data boundary if
+// requested.
+//   ns:   collect the nodes into this data structure.
+//   data: if true, include the control boundary.
+void Node::collect_nodes_in_all_ctrl(GrowableArray<Node*> *ns, bool data) const {
+  collect_nodes_in((Node*) this, ns, false, data);
+}
+
+//------------------collect_nodes_out_all_ctrl_boundary------------------------
+// Collect the entire output graph until hitting control node boundaries, and
+// include those.
+void Node::collect_nodes_out_all_ctrl_boundary(GrowableArray<Node*> *ns) const {
+  // Perform a BFS and stop at control nodes.
+  GrowableArray<Node*> nodes(Compile::current()->unique());
+  nodes.push((Node*) this);
+  while (nodes.length() > 0) {
+    Node* current = nodes.pop();
+    if (NotANode(current)) {
+      continue;
+    }
+    ns->append_if_missing(current);
+    if (!current->is_CFG()) {
+      for (DUIterator i = current->outs(); current->has_out(i); i++) {
+        nodes.push(current->out(i));
+      }
+    }
+  }
+  ns->remove((Node*) this);
+}
+
 // VERIFICATION CODE
 // For each input edge to a node (ie - for each Use-Def edge), verify that
 // there is a corresponding Def-Use edge.
@@ -2173,6 +2396,11 @@
     st->print(" #"); _type->dump_on(st);
   }
 }
+
+void TypeNode::dump_compact_spec(outputStream *st) const {
+  st->print("#");
+  _type->dump_on(st);
+}
 #endif
 uint TypeNode::hash() const {
   return Node::hash() + _type->hash();
--- a/hotspot/src/share/vm/opto/node.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/node.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1038,13 +1038,35 @@
   Node* find(int idx) const;         // Search the graph for the given idx.
   Node* find_ctrl(int idx) const;    // Search control ancestors for the given idx.
   void dump() const { dump("\n"); }  // Print this node.
-  void dump(const char* suffix, outputStream *st = tty) const;// Print this node.
+  void dump(const char* suffix, bool mark = false, outputStream *st = tty) const; // Print this node.
   void dump(int depth) const;        // Print this node, recursively to depth d
   void dump_ctrl(int depth) const;   // Print control nodes, to depth d
-  virtual void dump_req(outputStream *st = tty) const;     // Print required-edge info
-  virtual void dump_prec(outputStream *st = tty) const;    // Print precedence-edge info
-  virtual void dump_out(outputStream *st = tty) const;     // Print the output edge info
-  virtual void dump_spec(outputStream *st) const {}; // Print per-node info
+  void dump_comp() const;            // Print this node in compact representation.
+  // Print this node in compact representation.
+  void dump_comp(const char* suffix, outputStream *st = tty) const;
+  virtual void dump_req(outputStream *st = tty) const;    // Print required-edge info
+  virtual void dump_prec(outputStream *st = tty) const;   // Print precedence-edge info
+  virtual void dump_out(outputStream *st = tty) const;    // Print the output edge info
+  virtual void dump_spec(outputStream *st) const {};      // Print per-node info
+  // Print compact per-node info
+  virtual void dump_compact_spec(outputStream *st) const { dump_spec(st); }
+  void dump_related() const;             // Print related nodes (depends on node at hand).
+  // Print related nodes up to given depths for input and output nodes.
+  void dump_related(uint d_in, uint d_out) const;
+  void dump_related_compact() const;     // Print related nodes in compact representation.
+  // Collect related nodes.
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
+  // Collect nodes starting from this node, explicitly including/excluding control and data links.
+  void collect_nodes(GrowableArray<Node*> *ns, int d, bool ctrl, bool data) const;
+
+  // Node collectors, to be used in implementations of Node::rel().
+  // Collect the entire data input graph. Include control inputs if requested.
+  void collect_nodes_in_all_data(GrowableArray<Node*> *ns, bool ctrl) const;
+  // Collect the entire control input graph. Include data inputs if requested.
+  void collect_nodes_in_all_ctrl(GrowableArray<Node*> *ns, bool data) const;
+  // Collect the entire output graph until hitting and including control nodes.
+  void collect_nodes_out_all_ctrl_boundary(GrowableArray<Node*> *ns) const;
+
   void verify_edges(Unique_Node_List &visited); // Verify bi-directional edges
   void verify() const;               // Check Def-Use info for my subgraph
   static void verify_recur(const Node *n, int verify_depth, VectorSet &old_space, VectorSet &new_space);
@@ -1091,6 +1113,20 @@
 #endif
 };
 
+
+#ifndef PRODUCT
+
+// Used in debugging code to avoid walking across dead or uninitialized edges.
+inline bool NotANode(const Node* n) {
+  if (n == NULL)                   return true;
+  if (((intptr_t)n & 1) != 0)      return true;  // uninitialized, etc.
+  if (*(address*)n == badAddress)  return true;  // kill by Node::destruct
+  return false;
+}
+
+#endif
+
+
 //-----------------------------------------------------------------------------
 // Iterators over DU info, and associated Node functions.
 
@@ -1618,6 +1654,7 @@
   virtual       uint  ideal_reg() const;
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
+  virtual void dump_compact_spec(outputStream *st) const;
 #endif
 };
 
--- a/hotspot/src/share/vm/opto/output.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/output.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1504,6 +1504,13 @@
       n->emit(*cb, _regalloc);
       current_offset  = cb->insts_size();
 
+      // Above we only verified that there is enough space in the instruction section.
+      // However, the instruction may emit stubs that cause code buffer expansion.
+      // Bail out here if expansion failed due to a lack of code cache space.
+      if (failing()) {
+        return;
+      }
+
 #ifdef ASSERT
       if (n->size(_regalloc) < (current_offset-instr_offset)) {
         n->dump();
@@ -1632,11 +1639,14 @@
   if (_method) {
     // Emit the exception handler code.
     _code_offsets.set_value(CodeOffsets::Exceptions, HandlerImpl::emit_exception_handler(*cb));
+    if (failing()) {
+      return; // CodeBuffer::expand failed
+    }
     // Emit the deopt handler code.
     _code_offsets.set_value(CodeOffsets::Deopt, HandlerImpl::emit_deopt_handler(*cb));
 
     // Emit the MethodHandle deopt handler code (if required).
-    if (has_method_handle_invokes()) {
+    if (has_method_handle_invokes() && !failing()) {
       // We can use the same code as for the normal deopt handler, we
       // just need a different entry point address.
       _code_offsets.set_value(CodeOffsets::DeoptMH, HandlerImpl::emit_deopt_handler(*cb));
--- a/hotspot/src/share/vm/opto/rootnode.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/rootnode.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -88,3 +88,18 @@
 const RegMask &HaltNode::out_RegMask() const {
   return RegMask::Empty;
 }
+
+#ifndef PRODUCT
+//-----------------------------related-----------------------------------------
+// Include all control inputs in the related set, and also the input data
+// boundary. In compact mode, include all inputs till level 2. Also include
+// all outputs at level 1.
+void HaltNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  if (compact) {
+    this->collect_nodes(in_rel, 2, false, false);
+  } else {
+    this->collect_nodes_in_all_ctrl(in_rel, true);
+  }
+  this->collect_nodes(out_rel, -1, false, false);
+}
+#endif
--- a/hotspot/src/share/vm/opto/rootnode.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/rootnode.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,6 +64,10 @@
   virtual const RegMask &out_RegMask() const;
   virtual uint ideal_reg() const { return NotAMachineReg; }
   virtual uint match_edge(uint idx) const { return 0; }
+
+#ifndef PRODUCT
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
+#endif
 };
 
 #endif // SHARE_VM_OPTO_ROOTNODE_HPP
--- a/hotspot/src/share/vm/opto/subnode.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/subnode.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -498,6 +498,37 @@
   return this;
 }
 
+#ifndef PRODUCT
+//----------------------------related------------------------------------------
+// Related nodes of comparison nodes include all data inputs (until hitting a
+// control boundary) as well as all outputs until and including control nodes
+// as well as their projections. In compact mode, data inputs till depth 1 and
+// all outputs till depth 1 are considered.
+void CmpNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  if (compact) {
+    this->collect_nodes(in_rel, 1, false, true);
+    this->collect_nodes(out_rel, -1, false, false);
+  } else {
+    this->collect_nodes_in_all_data(in_rel, false);
+    this->collect_nodes_out_all_ctrl_boundary(out_rel);
+    // Now, find all control nodes in out_rel, and include their projections
+    // and projection targets (if any) in the result.
+    GrowableArray<Node*> proj(Compile::current()->unique());
+    for (GrowableArrayIterator<Node*> it = out_rel->begin(); it != out_rel->end(); ++it) {
+      Node* n = *it;
+      if (n->is_CFG() && !n->is_Proj()) {
+        // Assume projections and projection targets are found at levels 1 and 2.
+        n->collect_nodes(&proj, -2, false, false);
+        for (GrowableArrayIterator<Node*> p = proj.begin(); p != proj.end(); ++p) {
+          out_rel->append_if_missing(*p);
+        }
+        proj.clear();
+      }
+    }
+  }
+}
+#endif
+
 //=============================================================================
 //------------------------------cmp--------------------------------------------
 // Simplify a CmpI (compare 2 integers) node, based on local information.
@@ -1396,17 +1427,31 @@
   return _test.cc2logical( phase->type( in(1) ) );
 }
 
+#ifndef PRODUCT
 //------------------------------dump_spec--------------------------------------
 // Dump special per-node info
-#ifndef PRODUCT
 void BoolNode::dump_spec(outputStream *st) const {
   st->print("[");
   _test.dump_on(st);
   st->print("]");
 }
+
+//-------------------------------related---------------------------------------
+// A BoolNode's related nodes are all of its data inputs, and all of its
+// outputs until control nodes are hit, which are included. In compact
+// representation, inputs till level 3 and immediate outputs are included.
+void BoolNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
+  if (compact) {
+    this->collect_nodes(in_rel, 3, false, true);
+    this->collect_nodes(out_rel, -1, false, false);
+  } else {
+    this->collect_nodes_in_all_data(in_rel, false);
+    this->collect_nodes_out_all_ctrl_boundary(out_rel);
+  }
+}
 #endif
 
-//------------------------------is_counted_loop_exit_test--------------------------------------
+//----------------------is_counted_loop_exit_test------------------------------
 // Returns true if node is used by a counted loop node.
 bool BoolNode::is_counted_loop_exit_test() {
   for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) {
--- a/hotspot/src/share/vm/opto/subnode.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/opto/subnode.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,6 @@
   // Supplied function to return the additive identity type.
   // This is returned whenever the subtracts inputs are the same.
   virtual const Type *add_id() const = 0;
-
 };
 
 
@@ -140,6 +139,13 @@
   const Type *add_id() const { return TypeInt::ZERO; }
   const Type *bottom_type() const { return TypeInt::CC; }
   virtual uint ideal_reg() const { return Op_RegFlags; }
+
+#ifndef PRODUCT
+  // CmpNode and subclasses include all data inputs (until hitting a control
+  // boundary) in their related node set, as well as all outputs until and
+  // including eventual control nodes and their projections.
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
+#endif
 };
 
 //------------------------------CmpINode---------------------------------------
@@ -311,6 +317,7 @@
   bool is_counted_loop_exit_test();
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const;
+  virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const;
 #endif
 };
 
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -70,7 +70,10 @@
 #endif
 
   // The default CICompilerCount's value is CI_COMPILER_COUNT.
-  assert(min_number_of_compiler_threads <= CI_COMPILER_COUNT, "minimum should be less or equal default number");
+  // With a client VM, -XX:+TieredCompilation causes TieredCompilation
+  // to be true here (the option is validated later) and
+  // min_number_of_compiler_threads to exceed CI_COMPILER_COUNT.
+  min_number_of_compiler_threads = MIN2(min_number_of_compiler_threads, CI_COMPILER_COUNT);
 
   if (*value < (intx)min_number_of_compiler_threads) {
     if (verbose == true) {
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -848,6 +848,9 @@
   product(bool, UseCRC32CIntrinsics, false,                                 \
           "use intrinsics for java.util.zip.CRC32C")                        \
                                                                             \
+  diagnostic(ccstrlist, DisableIntrinsic, "",                               \
+         "do not expand intrinsics whose (internal) names appear here")     \
+                                                                            \
   develop(bool, TraceCallFixup, false,                                      \
           "Trace all call fixups")                                          \
                                                                             \
@@ -3913,7 +3916,7 @@
   product(bool, PerfDisableSharedMem, false,                                \
           "Store performance data in standard memory")                      \
                                                                             \
-  product(intx, PerfDataMemorySize, 32*K,                                   \
+  product(intx, PerfDataMemorySize, 64*K,                                   \
           "Size of performance data memory region. Will be rounded "        \
           "up to a multiple of the native os page size.")                   \
                                                                             \
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Wed Jul 05 20:45:16 2017 +0200
@@ -37,6 +37,7 @@
 #include "services/management.hpp"
 #include "services/writeableFlags.hpp"
 #include "utilities/macros.hpp"
+#include "oops/objArrayOop.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
@@ -57,6 +58,8 @@
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<VMUptimeDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(full_export, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapInfoDCmd>(full_export, true, false));
+  DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<FinalizerInfoDCmd>(full_export, true, false));
 #if INCLUDE_SERVICES // Heap dumping/inspection supported
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false));
   DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(full_export, true, false));
@@ -333,6 +336,60 @@
                          vmSymbols::void_method_signature(), CHECK);
 }
 
+void HeapInfoDCmd::execute(DCmdSource source, TRAPS) {
+  Universe::heap()->print_on(output());
+}
+
+void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) {
+  ResourceMark rm;
+
+
+  Klass* k = SystemDictionary::resolve_or_null(
+    vmSymbols::finalizer_histogram_klass(), THREAD);
+  assert(k != NULL, "FinalizerHistogram class is not accessible");
+
+  instanceKlassHandle klass(THREAD, k);
+  JavaValue result(T_ARRAY);
+
+  // We are calling lang.ref.FinalizerHistogram.getFinalizerHistogram() method
+  // and expect it to return array of FinalizerHistogramEntry as Object[]
+
+  JavaCalls::call_static(&result, klass,
+                         vmSymbols::get_finalizer_histogram_name(),
+                         vmSymbols::void_finalizer_histogram_entry_array_signature(), CHECK);
+
+  objArrayOop result_oop = (objArrayOop) result.get_jobject();
+  if (result_oop->length() == 0) {
+    output()->print_cr("No instances waiting for finalization found");
+    return;
+  }
+
+  oop foop = result_oop->obj_at(0);
+  InstanceKlass* ik = InstanceKlass::cast(foop->klass());
+
+  fieldDescriptor count_fd, name_fd;
+
+  Klass* count_res = ik->find_field(
+    vmSymbols::finalizer_histogram_entry_count_field(), vmSymbols::int_signature(), &count_fd);
+
+  Klass* name_res = ik->find_field(
+    vmSymbols::finalizer_histogram_entry_name_field(), vmSymbols::string_signature(), &name_fd);
+
+  assert(count_res != NULL && name_res != NULL, "Unexpected layout of FinalizerHistogramEntry");
+
+  output()->print_cr("Unreachable instances waiting for finalization");
+  output()->print_cr("#instances  class name");
+  output()->print_cr("-----------------------");
+
+  for (int i = 0; i < result_oop->length(); ++i) {
+    oop element_oop = result_oop->obj_at(i);
+    oop str_oop = element_oop->obj_field(name_fd.offset());
+    char *name = java_lang_String::as_utf8_string(str_oop);
+    int count = element_oop->int_field(count_fd.offset());
+    output()->print_cr("%10d  %s", count, name);
+  }
+}
+
 #if INCLUDE_SERVICES // Heap dumping/inspection supported
 HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) :
                            DCmdWithParser(output, heap),
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp	Wed Jul 05 20:45:16 2017 +0200
@@ -241,6 +241,46 @@
     virtual void execute(DCmdSource source, TRAPS);
 };
 
+class HeapInfoDCmd : public DCmd {
+public:
+  HeapInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
+  static const char* name() { return "GC.heap_info"; }
+  static const char* description() {
+    return "Provide generic Java heap information.";
+  }
+  static const char* impact() {
+    return "Medium";
+  }
+  static int num_arguments() { return 0; }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+      "monitor", NULL};
+      return p;
+  }
+
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
+class FinalizerInfoDCmd : public DCmd {
+public:
+  FinalizerInfoDCmd(outputStream* output, bool heap) : DCmd(output, heap) { }
+  static const char* name() { return "GC.finalizer_info"; }
+  static const char* description() {
+    return "Provide information about Java finalization queue.";
+  }
+  static const char* impact() {
+    return "Medium";
+  }
+  static int num_arguments() { return 0; }
+  static const JavaPermission permission() {
+    JavaPermission p = {"java.lang.management.ManagementPermission",
+      "monitor", NULL};
+      return p;
+  }
+
+  virtual void execute(DCmdSource source, TRAPS);
+};
+
 #if INCLUDE_SERVICES   // Heap dumping supported
 // See also: dump_heap in attachListener.cpp
 class HeapDumpDCmd : public DCmdWithParser {
--- a/hotspot/test/compiler/arguments/CheckCICompilerCount.java	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/test/compiler/arguments/CheckCICompilerCount.java	Wed Jul 05 20:45:16 2017 +0200
@@ -26,6 +26,7 @@
 /*
  * @test CheckCheckCICompilerCount
  * @bug 8130858
+ * @bug 8132525
  * @summary Check that correct range of values for CICompilerCount are allowed depending on whether tiered is enabled or not
  * @library /testlibrary
  * @modules java.base/sun.misc
@@ -36,12 +37,28 @@
 public class CheckCICompilerCount {
     private static final String[][] NON_TIERED_ARGUMENTS = {
         {
+            "-server",
             "-XX:-TieredCompilation",
             "-XX:+PrintFlagsFinal",
             "-XX:CICompilerCount=0",
             "-version"
         },
         {
+            "-server",
+            "-XX:-TieredCompilation",
+            "-XX:+PrintFlagsFinal",
+            "-XX:CICompilerCount=1",
+            "-version"
+        },
+        {
+            "-client",
+            "-XX:-TieredCompilation",
+            "-XX:+PrintFlagsFinal",
+            "-XX:CICompilerCount=0",
+            "-version"
+        },
+        {
+            "-client",
             "-XX:-TieredCompilation",
             "-XX:+PrintFlagsFinal",
             "-XX:CICompilerCount=1",
@@ -56,22 +73,47 @@
         },
         {
             "intx CICompilerCount                          := 1                                   {product}"
+        },
+        {
+            "CICompilerCount=0 must be at least 1",
+            "Improperly specified VM option 'CICompilerCount=0'"
+        },
+        {
+            "intx CICompilerCount                          := 1                                   {product}"
         }
     };
 
     private static final int[] NON_TIERED_EXIT = {
         1,
+        0,
+        1,
         0
     };
 
     private static final String[][] TIERED_ARGUMENTS = {
         {
+            "-server",
             "-XX:+TieredCompilation",
             "-XX:+PrintFlagsFinal",
             "-XX:CICompilerCount=1",
             "-version"
         },
         {
+            "-server",
+            "-XX:+TieredCompilation",
+            "-XX:+PrintFlagsFinal",
+            "-XX:CICompilerCount=2",
+            "-version"
+        },
+        {
+            "-client",
+            "-XX:+TieredCompilation",
+            "-XX:+PrintFlagsFinal",
+            "-XX:CICompilerCount=1",
+            "-version"
+        },
+        {
+            "-client",
             "-XX:+TieredCompilation",
             "-XX:+PrintFlagsFinal",
             "-XX:CICompilerCount=2",
@@ -86,11 +128,20 @@
         },
         {
             "intx CICompilerCount                          := 2                                   {product}"
+        },
+        {
+            "CICompilerCount=1 must be at least 2",
+            "Improperly specified VM option 'CICompilerCount=1'"
+        },
+        {
+            "intx CICompilerCount                          := 2                                   {product}"
         }
     };
 
     private static final int[] TIERED_EXIT = {
         1,
+        0,
+        1,
         0
     };
 
--- a/hotspot/test/runtime/CommandLine/PrintTouchedMethods.java	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/test/runtime/CommandLine/PrintTouchedMethods.java	Wed Jul 05 20:45:16 2017 +0200
@@ -87,6 +87,24 @@
       output.shouldNotContain("TestLogTouchedMethods.methodB:()V");
       output.shouldHaveExitValue(0);
 
+      String[] javaArgs4 = {"-XX:+UnlockDiagnosticVMOptions", "-Xint", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "-XX:-TieredCompilation", "TestLogTouchedMethods"};
+      pb = ProcessTools.createJavaProcessBuilder(javaArgs4);
+      output = new OutputAnalyzer(pb.start());
+      lines = output.asLines();
+
+      if (lines.size() < 1) {
+        throw new Exception("Empty output");
+      }
+
+      first = lines.get(0);
+      if (!first.equals("# Method::print_touched_methods version 1")) {
+        throw new Exception("First line mismatch");
+      }
+
+      output.shouldContain("TestLogTouchedMethods.methodA:()V");
+      output.shouldNotContain("TestLogTouchedMethods.methodB:()V");
+      output.shouldHaveExitValue(0);
+
       // Test jcmd PrintTouchedMethods VM.print_touched_methods
       String pid = Integer.toString(ProcessTools.getProcessId());
       pb = new ProcessBuilder();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/gc/FinalizerInfoTest.java	Wed Jul 05 20:45:16 2017 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.PidJcmdExecutor;
+
+/*
+ * @test
+ * @summary
+ * @library /testlibrary
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @run testng FinalizerInfoTest
+ */
+public class FinalizerInfoTest {
+    static ReentrantLock lock = new ReentrantLock();
+    static volatile int wasInitialized = 0;
+    static volatile int wasTrapped = 0;
+    static final String cmd = "GC.finalizer_info";
+    static final int objectsCount = 1000;
+
+    class MyObject {
+        public MyObject() {
+            // Make sure object allocation/deallocation is not optimized out
+            wasInitialized += 1;
+        }
+
+        protected void finalize() {
+            // Trap the object in a finalization queue
+            wasTrapped += 1;
+            lock.lock();
+        }
+    }
+
+    public void run(CommandExecutor executor) {
+        try {
+            lock.lock();
+            for(int i = 0; i < objectsCount; ++i) {
+                new MyObject();
+            }
+            System.out.println("Objects initialized: " + objectsCount);
+            System.gc();
+
+            while(wasTrapped < 1) {
+                // Waiting for gc thread.
+            }
+
+            OutputAnalyzer output = executor.execute(cmd);
+            output.shouldContain("MyObject");
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    @Test
+    public void pid() {
+        run(new PidJcmdExecutor());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/gc/HeapInfoTest.java	Wed Jul 05 20:45:16 2017 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+import java.io.IOException;
+
+import jdk.test.lib.dcmd.CommandExecutor;
+import jdk.test.lib.dcmd.PidJcmdExecutor;
+import jdk.test.lib.OutputAnalyzer;
+
+
+/*
+ * @test
+ * @summary Test of diagnostic command GC.heap_info
+ * @library /testlibrary
+ * @build jdk.test.lib.*
+ * @build jdk.test.lib.dcmd.*
+ * @run testng HeapInfoTest
+ */
+public class HeapInfoTest {
+    public void run(CommandExecutor executor) {
+        String cmd = "GC.heap_info";
+        OutputAnalyzer output = executor.execute(cmd);
+        output.shouldContain("Metaspace");
+    }
+
+    @Test
+    public void pid() {
+        run(new PidJcmdExecutor());
+    }
+}
+
--- a/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java	Wed Jul 05 20:45:16 2017 +0200
@@ -21,15 +21,13 @@
  * questions.
  */
 
-import org.testng.annotations.Test;
-import org.testng.Assert;
-
+import java.util.concurrent.Phaser;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.TimeoutException;
 
 import jdk.test.lib.dcmd.CommandExecutor;
 import jdk.test.lib.dcmd.JMXExecutor;
+import jdk.test.lib.Utils;
 
 /*
  * @test
@@ -41,62 +39,71 @@
  *          jdk.jvmstat/sun.jvmstat.monitor
  * @build jdk.test.lib.*
  * @build jdk.test.lib.dcmd.*
- * @run testng RunFinalizationTest
+ * @run main/othervm RunFinalizationTest
  */
 public class RunFinalizationTest {
-    static ReentrantLock lock = new ReentrantLock();
-    static Condition cond = lock.newCondition();
+    private static final long TIMEOUT = Utils.adjustTimeout(15000); // 15s
+    private static final Phaser ph = new Phaser(3);
     static volatile boolean wasFinalized = false;
     static volatile boolean wasInitialized = false;
 
-    class MyObject {
+    static class MyObject {
         public MyObject() {
             /* Make sure object allocation/deallocation is not optimized out */
             wasInitialized = true;
         }
 
         protected void finalize() {
-            lock.lock();
-            wasFinalized = true;
-            cond.signalAll();
-            lock.unlock();
+            if (!Thread.currentThread().getName().equals("Finalizer")) {
+                wasFinalized = true;
+                ph.arrive();
+            } else {
+                ph.arriveAndAwaitAdvance();
+            }
         }
     }
 
     public static MyObject o;
 
-    public void run(CommandExecutor executor) {
-        lock.lock();
+    private static void run(CommandExecutor executor) {
         o = new MyObject();
         o = null;
         System.gc();
         executor.execute("GC.run_finalization");
 
-        int waited = 0;
-        int waitTime = 15;
-
-        try {
-            System.out.println("Waiting for signal from finalizer");
+        System.out.println("Waiting for signal from finalizer");
 
-            while (!cond.await(waitTime, TimeUnit.SECONDS)) {
-                waited += waitTime;
-                System.out.println(String.format("Waited %d seconds", waited));
+        long targetTime = System.currentTimeMillis() + TIMEOUT;
+        while (System.currentTimeMillis() < targetTime) {
+            try {
+                ph.awaitAdvanceInterruptibly(ph.arrive(), 200, TimeUnit.MILLISECONDS);
+                System.out.println("Received signal");
+                break;
+            } catch (InterruptedException e) {
+                fail("Test error: Interrupted while waiting for signal from finalizer", e);
+            } catch (TimeoutException e) {
+                System.out.println("Haven't received signal in 200ms. Retrying ...");
             }
-
-            System.out.println("Received signal");
-        } catch (InterruptedException e) {
-            Assert.fail("Test error: Interrupted while waiting for signal from finalizer", e);
-        } finally {
-            lock.unlock();
         }
 
         if (!wasFinalized) {
-            Assert.fail("Test failure: Object was not finalized");
+            fail("Test failure: Object was not finalized");
         }
     }
 
-    @Test
-    public void jmx() {
-        run(new JMXExecutor());
+    public static void main(String ... args) {
+        MyObject o = new MyObject();
+        o = null;
+        Runtime.getRuntime().addShutdownHook(new Thread(()->{
+            run(new JMXExecutor());
+        }));
+    }
+
+    private static void fail(String msg, Exception e) {
+        throw new Error(msg, e);
+    }
+
+    private static void fail(String msg) {
+        throw new Error(msg);
     }
 }
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Thu Aug 13 14:14:42 2015 -0700
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java	Wed Jul 05 20:45:16 2017 +0200
@@ -314,9 +314,8 @@
      */
     public static String fileAsString(String filename) throws IOException {
         Path filePath = Paths.get(filename);
-        return Files.exists(filePath)
-            ? Files.lines(filePath).collect(Collectors.joining(NEW_LINE))
-            : null;
+        if (!Files.exists(filePath)) return null;
+        return new String(Files.readAllBytes(filePath));
     }
 
     /**