Merge
authorduke
Wed, 05 Jul 2017 20:37:43 +0200
changeset 31087 59d2a5d94dd6
parent 31086 d24a2c340a47 (current diff)
parent 31055 42a53f14bc5a (diff)
child 31091 674722d6d0ef
Merge
--- a/.hgtags-top-repo	Thu Jun 11 20:18:55 2015 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 20:37:43 2017 +0200
@@ -310,3 +310,4 @@
 7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65
 dc6e8336f51bb6b67b7245766179eab5ca7720b4 jdk9-b66
 f546760134eb861fcfecd4ce611b0040b0d25a6a jdk9-b67
+70e4272790b6199e9ca89df2758ff9cb58ec4125 jdk9-b68
--- a/hotspot/.hgtags	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 20:37:43 2017 +0200
@@ -470,3 +470,4 @@
 e7ae94c4f35e940ea423fc1dd260435df34a77c0 jdk9-b65
 197e94e0dacddd16816f101d24fc0442ab518326 jdk9-b66
 d47dfabd16d48eb96a451edd1b61194a39ee0eb5 jdk9-b67
+11af3990d56c97b40318bc1f20608e86f051a3f7 jdk9-b68
--- a/hotspot/make/linux/makefiles/dtrace.make	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/make/linux/makefiles/dtrace.make	Wed Jul 05 20:37:43 2017 +0200
@@ -31,8 +31,8 @@
 REASON = "This JDK does not support SDT probes"
 else
 
-# We need a recent GCC for the default
-ifeq "$(shell expr \( $(CC_VER_MAJOR) \>= 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) )" "0"
+# We need a recent GCC for the default (4.4 or later)
+ifeq "$(shell expr \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 4 \) \) \| \( $(CC_VER_MAJOR) \>= 5 \) )" "0"
 REASON = "gcc version is too old"
 else
 
--- a/hotspot/make/test/JtregNative.gmk	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/make/test/JtregNative.gmk	Wed Jul 05 20:37:43 2017 +0200
@@ -44,6 +44,7 @@
     $(HOTSPOT_TOPDIR)/test/native_sanity \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
+    $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
     #
 
 BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Jul 05 20:37:43 2017 +0200
@@ -3372,6 +3372,25 @@
   interface(CONST_INTER);
 %}
 
+// Integer Immediate: 0-bit
+operand immI0() %{
+  predicate(n->get_int() == 0);
+  match(ConI);
+  op_cost(0);
+
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Integer Immediate: 5-bit
+operand immI5() %{
+  predicate(Assembler::is_simm5(n->get_int()));
+  match(ConI);
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
 // Integer Immediate: 8-bit
 operand immI8() %{
   predicate(Assembler::is_simm8(n->get_int()));
@@ -3381,6 +3400,25 @@
   interface(CONST_INTER);
 %}
 
+// Integer Immediate: the value 10
+operand immI10() %{
+  predicate(n->get_int() == 10);
+  match(ConI);
+  op_cost(0);
+
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Integer Immediate: 11-bit
+operand immI11() %{
+  predicate(Assembler::is_simm11(n->get_int()));
+  match(ConI);
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
 // Integer Immediate: 13-bit
 operand immI13() %{
   predicate(Assembler::is_simm13(n->get_int()));
@@ -3410,84 +3448,6 @@
   interface(CONST_INTER);
 %}
 
-// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
-operand immU12() %{
-  predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
-  match(ConI);
-  op_cost(0);
-
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
-// Integer Immediate: 6-bit
-operand immU6() %{
-  predicate(n->get_int() >= 0 && n->get_int() <= 63);
-  match(ConI);
-  op_cost(0);
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
-// Integer Immediate: 11-bit
-operand immI11() %{
-  predicate(Assembler::is_simm11(n->get_int()));
-  match(ConI);
-  op_cost(0);
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
-// Integer Immediate: 5-bit
-operand immI5() %{
-  predicate(Assembler::is_simm5(n->get_int()));
-  match(ConI);
-  op_cost(0);
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
-// Int Immediate non-negative
-operand immU31()
-%{
-  predicate(n->get_int() >= 0);
-  match(ConI);
-
-  op_cost(0);
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
-// Integer Immediate: 0-bit
-operand immI0() %{
-  predicate(n->get_int() == 0);
-  match(ConI);
-  op_cost(0);
-
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
-// Integer Immediate: the value 10
-operand immI10() %{
-  predicate(n->get_int() == 10);
-  match(ConI);
-  op_cost(0);
-
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
-// Integer Immediate: the values 0-31
-operand immU5() %{
-  predicate(n->get_int() >= 0 && n->get_int() <= 31);
-  match(ConI);
-  op_cost(0);
-
-  format %{ %}
-  interface(CONST_INTER);
-%}
-
 // Integer Immediate: the values 1-31
 operand immI_1_31() %{
   predicate(n->get_int() >= 1 && n->get_int() <= 31);
@@ -3529,7 +3489,6 @@
   format %{ %}
   interface(CONST_INTER);
 %}
-
 // Integer Immediate: the value 255
 operand immI_255() %{
   predicate( n->get_int() == 255 );
@@ -3550,6 +3509,46 @@
   interface(CONST_INTER);
 %}
 
+// Integer Immediate: the values 0-31
+operand immU5() %{
+  predicate(n->get_int() >= 0 && n->get_int() <= 31);
+  match(ConI);
+  op_cost(0);
+
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Integer Immediate: 6-bit
+operand immU6() %{
+  predicate(n->get_int() >= 0 && n->get_int() <= 63);
+  match(ConI);
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Unsigned Integer Immediate: 12-bit (non-negative that fits in simm13)
+operand immU12() %{
+  predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
+  match(ConI);
+  op_cost(0);
+
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Integer Immediate non-negative
+operand immU31()
+%{
+  predicate(n->get_int() >= 0);
+  match(ConI);
+
+  op_cost(0);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
 // Long Immediate: the value FF
 operand immL_FF() %{
   predicate( n->get_long() == 0xFFL );
@@ -5653,17 +5652,17 @@
   ins_pipe(iload_mem);
 %}
 
-// Load Unsigned Byte (8 bit UNsigned) with 8-bit mask into Long Register
-instruct loadUB2L_immI8(iRegL dst, memory mem, immI8 mask) %{
+// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
+instruct loadUB2L_immI(iRegL dst, memory mem, immI mask) %{
   match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
   ins_cost(MEMORY_REF_COST + DEFAULT_COST);
 
   size(2*4);
-  format %{ "LDUB   $mem,$dst\t# ubyte & 8-bit mask -> long\n\t"
-            "AND    $dst,$mask,$dst" %}
+  format %{ "LDUB   $mem,$dst\t# ubyte & 32-bit mask -> long\n\t"
+            "AND    $dst,right_n_bits($mask, 8),$dst" %}
   ins_encode %{
     __ ldub($mem$$Address, $dst$$Register);
-    __ and3($dst$$Register, $mask$$constant, $dst$$Register);
+    __ and3($dst$$Register, $mask$$constant & right_n_bits(8), $dst$$Register);
   %}
   ins_pipe(iload_mem);
 %}
@@ -5776,20 +5775,20 @@
   ins_pipe(iload_mem);
 %}
 
-// Load Unsigned Short/Char (16bit UNsigned) with a 16-bit mask into a Long Register
-instruct loadUS2L_immI16(iRegL dst, memory mem, immI16 mask, iRegL tmp) %{
+// Load Unsigned Short/Char (16bit UNsigned) with a 32-bit mask into a Long Register
+instruct loadUS2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{
   match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
   effect(TEMP dst, TEMP tmp);
   ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
 
-  format %{ "LDUH   $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t"
-            "SET    $mask,$tmp\n\t"
+  format %{ "LDUH   $mem,$dst\t! ushort/char & 32-bit mask -> long\n\t"
+            "SET    right_n_bits($mask, 16),$tmp\n\t"
             "AND    $dst,$tmp,$dst" %}
   ins_encode %{
     Register Rdst = $dst$$Register;
     Register Rtmp = $tmp$$Register;
     __ lduh($mem$$Address, Rdst);
-    __ set($mask$$constant, Rtmp);
+    __ set($mask$$constant & right_n_bits(16), Rtmp);
     __ and3(Rdst, Rtmp, Rdst);
   %}
   ins_pipe(iload_mem);
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Jul 05 20:37:43 2017 +0200
@@ -5431,18 +5431,18 @@
 %}
 
 // Load Unsigned Byte (8 bit UNsigned) with mask into Long Register
-instruct loadUB2L_immI8(eRegL dst, memory mem, immI8 mask, eFlagsReg cr) %{
+instruct loadUB2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
   match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
   effect(KILL cr);
 
-  format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 8-bit mask -> long\n\t"
+  format %{ "MOVZX8 $dst.lo,$mem\t# ubyte & 32-bit mask -> long\n\t"
             "XOR    $dst.hi,$dst.hi\n\t"
-            "AND    $dst.lo,$mask" %}
+            "AND    $dst.lo,right_n_bits($mask, 8)" %}
   ins_encode %{
     Register Rdst = $dst$$Register;
     __ movzbl(Rdst, $mem$$Address);
     __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
-    __ andl(Rdst, $mask$$constant);
+    __ andl(Rdst, $mask$$constant & right_n_bits(8));
   %}
   ins_pipe(ialu_reg_mem);
 %}
@@ -5550,19 +5550,19 @@
   ins_pipe(ialu_reg_mem);
 %}
 
-// Load Unsigned Short/Char (16 bit UNsigned) with a 16-bit mask into Long Register
-instruct loadUS2L_immI16(eRegL dst, memory mem, immI16 mask, eFlagsReg cr) %{
+// Load Unsigned Short/Char (16 bit UNsigned) with a 32-bit mask into Long Register
+instruct loadUS2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
   match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
   effect(KILL cr);
 
-  format %{ "MOVZX  $dst.lo, $mem\t# ushort/char & 16-bit mask -> long\n\t"
+  format %{ "MOVZX  $dst.lo, $mem\t# ushort/char & 32-bit mask -> long\n\t"
             "XOR    $dst.hi,$dst.hi\n\t"
-            "AND    $dst.lo,$mask" %}
+            "AND    $dst.lo,right_n_bits($mask, 16)" %}
   ins_encode %{
     Register Rdst = $dst$$Register;
     __ movzwl(Rdst, $mem$$Address);
     __ xorl(HIGH_FROM_LOW(Rdst), HIGH_FROM_LOW(Rdst));
-    __ andl(Rdst, $mask$$constant);
+    __ andl(Rdst, $mask$$constant & right_n_bits(16));
   %}
   ins_pipe(ialu_reg_mem);
 %}
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Jul 05 20:37:43 2017 +0200
@@ -4753,17 +4753,17 @@
   ins_pipe(ialu_reg_mem);
 %}
 
-// Load Unsigned Byte (8 bit UNsigned) with a 8-bit mask into Long Register
-instruct loadUB2L_immI8(rRegL dst, memory mem, immI8 mask, rFlagsReg cr) %{
+// Load Unsigned Byte (8 bit UNsigned) with 32-bit mask into Long Register
+instruct loadUB2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
   match(Set dst (ConvI2L (AndI (LoadUB mem) mask)));
   effect(KILL cr);
 
-  format %{ "movzbq  $dst, $mem\t# ubyte & 8-bit mask -> long\n\t"
-            "andl    $dst, $mask" %}
+  format %{ "movzbq  $dst, $mem\t# ubyte & 32-bit mask -> long\n\t"
+            "andl    $dst, right_n_bits($mask, 8)" %}
   ins_encode %{
     Register Rdst = $dst$$Register;
     __ movzbq(Rdst, $mem$$Address);
-    __ andl(Rdst, $mask$$constant);
+    __ andl(Rdst, $mask$$constant & right_n_bits(8));
   %}
   ins_pipe(ialu_reg_mem);
 %}
@@ -4863,17 +4863,17 @@
   ins_pipe(ialu_reg_mem);
 %}
 
-// Load Unsigned Short/Char (16 bit UNsigned) with mask into Long Register
-instruct loadUS2L_immI16(rRegL dst, memory mem, immI16 mask, rFlagsReg cr) %{
+// Load Unsigned Short/Char (16 bit UNsigned) with 32-bit mask into Long Register
+instruct loadUS2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
   match(Set dst (ConvI2L (AndI (LoadUS mem) mask)));
   effect(KILL cr);
 
-  format %{ "movzwq  $dst, $mem\t# ushort/char & 16-bit mask -> long\n\t"
-            "andl    $dst, $mask" %}
+  format %{ "movzwq  $dst, $mem\t# ushort/char & 32-bit mask -> long\n\t"
+            "andl    $dst, right_n_bits($mask, 16)" %}
   ins_encode %{
     Register Rdst = $dst$$Register;
     __ movzwq(Rdst, $mem$$Address);
-    __ andl(Rdst, $mask$$constant);
+    __ andl(Rdst, $mask$$constant & right_n_bits(16));
   %}
   ins_pipe(ialu_reg_mem);
 %}
--- a/hotspot/src/os/aix/vm/os_aix.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/os/aix/vm/os_aix.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1267,10 +1267,6 @@
 // Note: os::abort() might be called very early during initialization, or
 // called from signal handler. Before adding something to os::abort(), make
 // sure it is async-safe and can handle partially initialized VM.
-void os::abort(bool dump_core) {
-  abort(dump_core, NULL, NULL);
-}
-
 void os::abort(bool dump_core, void* siginfo, void* context) {
   os::shutdown();
   if (dump_core) {
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1131,10 +1131,6 @@
 // Note: os::abort() might be called very early during initialization, or
 // called from signal handler. Before adding something to os::abort(), make
 // sure it is async-safe and can handle partially initialized VM.
-void os::abort(bool dump_core) {
-  abort(dump_core, NULL, NULL);
-}
-
 void os::abort(bool dump_core, void* siginfo, void* context) {
   os::shutdown();
   if (dump_core) {
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1478,10 +1478,6 @@
 // Note: os::abort() might be called very early during initialization, or
 // called from signal handler. Before adding something to os::abort(), make
 // sure it is async-safe and can handle partially initialized VM.
-void os::abort(bool dump_core) {
-  abort(dump_core, NULL, NULL);
-}
-
 void os::abort(bool dump_core, void* siginfo, void* context) {
   os::shutdown();
   if (dump_core) {
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1520,10 +1520,6 @@
 // Note: os::abort() might be called very early during initialization, or
 // called from signal handler. Before adding something to os::abort(), make
 // sure it is async-safe and can handle partially initialized VM.
-void os::abort(bool dump_core) {
-  abort(dump_core, NULL, NULL);
-}
-
 void os::abort(bool dump_core, void* siginfo, void* context) {
   os::shutdown();
   if (dump_core) {
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -997,7 +997,16 @@
   if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
     jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
     status = false;
-  } else {
+  }
+
+#ifndef ASSERT
+  if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
+    jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows");
+    status = false;
+  }
+#endif
+
+  if (status) {
     const char* cwd = get_current_directory(NULL, 0);
     int pid = current_process_id();
     if (cwd != NULL) {
@@ -1086,10 +1095,6 @@
   win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
 }
 
-void os::abort(bool dump_core) {
-  abort(dump_core, NULL, NULL);
-}
-
 // Die immediately, no exit hook, no abort hook, no cleanup.
 void os::die() {
   win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1);
--- a/hotspot/src/share/vm/ci/ciCallSite.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/ci/ciCallSite.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -50,25 +50,6 @@
 }
 
 // ------------------------------------------------------------------
-// ciCallSite::get_context
-//
-// Return the target MethodHandle of this CallSite.
-ciKlass* ciCallSite::get_context() {
-  assert(!is_constant_call_site(), "");
-
-  VM_ENTRY_MARK;
-  oop call_site_oop = get_oop();
-  InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site_oop);
-  if (ctxk == NULL) {
-    // The call site doesn't have a context associated. Set it to the default context.
-    oop def_context_oop = java_lang_invoke_CallSite::default_context();
-    java_lang_invoke_CallSite::set_context_cas(call_site_oop, def_context_oop, /*expected=*/NULL);
-    ctxk = MethodHandles::get_call_site_context(call_site_oop);
-  }
-  return (CURRENT_ENV->get_metadata(ctxk))->as_klass();
-}
-
-// ------------------------------------------------------------------
 // ciCallSite::print
 //
 // Print debugging information about the CallSite.
--- a/hotspot/src/share/vm/ci/ciCallSite.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/ci/ciCallSite.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -43,7 +43,6 @@
 
   // Return the target MethodHandle of this CallSite.
   ciMethodHandle* get_target() const;
-  ciKlass* get_context();
 
   void print();
 };
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -709,24 +709,23 @@
   KlassHandle h_holder(THREAD, holder);
   LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
   methodHandle dest_method;
+  LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
   switch (bc) {
   case Bytecodes::_invokestatic:
     dest_method =
-      LinkResolver::resolve_static_call_or_null(h_holder, name, sig, h_accessor);
+      LinkResolver::resolve_static_call_or_null(link_info);
     break;
   case Bytecodes::_invokespecial:
     dest_method =
-      LinkResolver::resolve_special_call_or_null(h_holder, name, sig, h_accessor);
+      LinkResolver::resolve_special_call_or_null(link_info);
     break;
   case Bytecodes::_invokeinterface:
     dest_method =
-      LinkResolver::linktime_resolve_interface_method_or_null(h_holder, name, sig,
-                                                              h_accessor, true);
+      LinkResolver::linktime_resolve_interface_method_or_null(link_info);
     break;
   case Bytecodes::_invokevirtual:
     dest_method =
-      LinkResolver::linktime_resolve_virtual_method_or_null(h_holder, name, sig,
-                                                            h_accessor, true);
+      LinkResolver::linktime_resolve_virtual_method_or_null(link_info);
     break;
   default: ShouldNotReachHere();
   }
--- a/hotspot/src/share/vm/ci/ciField.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/ci/ciField.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -352,11 +352,11 @@
     }
   }
 
+  LinkInfo link_info(_holder->get_instanceKlass(),
+                     _name->get_symbol(), _signature->get_symbol(),
+                     accessing_klass->get_Klass());
   fieldDescriptor result;
-  LinkResolver::resolve_field(result, _holder->get_instanceKlass(),
-                              _name->get_symbol(), _signature->get_symbol(),
-                              accessing_klass->get_Klass(), bc, true, false,
-                              KILL_COMPILE_ON_FATAL_(false));
+  LinkResolver::resolve_field(result, link_info, bc, false, KILL_COMPILE_ON_FATAL_(false));
 
   // update the hit-cache, unless there is a problem with memory scoping:
   if (accessing_klass->is_shared() || !is_shared()) {
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -453,8 +453,12 @@
 
   if (fields == NULL) {
     // This can happen if this class (java.lang.Class) has invisible fields.
-    _nonstatic_fields = super_fields;
-    return super_fields->length();
+    if (super_fields != NULL) {
+      _nonstatic_fields = super_fields;
+      return super_fields->length();
+    } else {
+      return 0;
+    }
   }
 
   int flen = fields->length();
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Wed Jul 05 20:37:43 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
@@ -786,6 +786,7 @@
    Symbol* h_name      = name()->get_symbol();
    Symbol* h_signature = signature()->get_symbol();
 
+   LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access);
    methodHandle m;
    // Only do exact lookup if receiver klass has been linked.  Otherwise,
    // the vtable has not been setup, and the LinkResolver will fail.
@@ -793,9 +794,9 @@
         ||
        InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) {
      if (holder()->is_interface()) {
-       m = LinkResolver::resolve_interface_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access);
+       m = LinkResolver::resolve_interface_call_or_null(h_recv, link_info);
      } else {
-       m = LinkResolver::resolve_virtual_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access);
+       m = LinkResolver::resolve_virtual_call_or_null(h_recv, link_info);
      }
    }
 
@@ -839,7 +840,8 @@
      Symbol* h_name = name()->get_symbol();
      Symbol* h_signature = signature()->get_symbol();
 
-     vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, h_recv, h_name, h_signature, caller_klass);
+     LinkInfo link_info(h_recv, h_name, h_signature, caller_klass);
+     vtable_index = LinkResolver::resolve_virtual_vtable_index(h_recv, link_info);
      if (vtable_index == Method::nonvirtual_vtable_index) {
        // A statically bound method.  Return "no such index".
        vtable_index = Method::invalid_vtable_index;
@@ -1285,10 +1287,8 @@
     EXCEPTION_MARK;
     HandleMark hm(THREAD);
     constantPoolHandle pool (THREAD, get_Method()->constants());
-    methodHandle spec_method;
-    KlassHandle  spec_klass;
     Bytecodes::Code code = (is_static ? Bytecodes::_invokestatic : Bytecodes::_invokevirtual);
-    LinkResolver::resolve_method_statically(spec_method, spec_klass, code, pool, refinfo_index, THREAD);
+    methodHandle spec_method = LinkResolver::resolve_method_statically(code, pool, refinfo_index, THREAD);
     if (HAS_PENDING_EXCEPTION) {
       CLEAR_PENDING_EXCEPTION;
       return false;
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -2967,47 +2967,42 @@
 
 int java_lang_invoke_CallSite::_target_offset;
 int java_lang_invoke_CallSite::_context_offset;
-int java_lang_invoke_CallSite::_default_context_offset;
 
 void java_lang_invoke_CallSite::compute_offsets() {
   Klass* k = SystemDictionary::CallSite_klass();
   if (k != NULL) {
     compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature());
-    compute_offset(_context_offset, k, vmSymbols::context_name(), vmSymbols::sun_misc_Cleaner_signature());
-    compute_offset(_default_context_offset, k,
-                   vmSymbols::DEFAULT_CONTEXT_name(), vmSymbols::sun_misc_Cleaner_signature(),
-                   /*is_static=*/true, /*allow_super=*/false);
+    compute_offset(_context_offset, k, vmSymbols::context_name(),
+                   vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature());
   }
 }
 
-oop java_lang_invoke_CallSite::context_volatile(oop call_site) {
-  assert(java_lang_invoke_CallSite::is_instance(call_site), "");
-
-  oop dep_oop = call_site->obj_field_volatile(_context_offset);
-  return dep_oop;
-}
-
-void java_lang_invoke_CallSite::set_context_volatile(oop call_site, oop context) {
+oop java_lang_invoke_CallSite::context(oop call_site) {
   assert(java_lang_invoke_CallSite::is_instance(call_site), "");
-  call_site->obj_field_put_volatile(_context_offset, context);
-}
-
-bool java_lang_invoke_CallSite::set_context_cas(oop call_site, oop context, oop expected) {
-  assert(java_lang_invoke_CallSite::is_instance(call_site), "");
-  HeapWord* context_addr = call_site->obj_field_addr<HeapWord>(_context_offset);
-  oop res = oopDesc::atomic_compare_exchange_oop(context, context_addr, expected, true);
-  bool success = (res == expected);
-  if (success) {
-    update_barrier_set((void*)context_addr, context);
+
+  oop dep_oop = call_site->obj_field(_context_offset);
+  return dep_oop;
+}
+
+// Support for java_lang_invoke_MethodHandleNatives_CallSiteContext
+
+int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset;
+
+void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() {
+  Klass* k = SystemDictionary::Context_klass();
+  if (k != NULL) {
+    CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
   }
-  return success;
-}
-
-oop java_lang_invoke_CallSite::default_context() {
-  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::CallSite_klass());
-  oop def_context_oop = ik->java_mirror()->obj_field(_default_context_offset);
-  assert(!oopDesc::is_null(def_context_oop), "");
-  return def_context_oop;
+}
+
+nmethodBucket* java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) {
+  assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "");
+  return (nmethodBucket*) (address) call_site->long_field(_vmdependencies_offset);
+}
+
+void java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(oop call_site, nmethodBucket* context) {
+  assert(java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(call_site), "");
+  call_site->long_field_put(_vmdependencies_offset, (jlong) (address) context);
 }
 
 // Support for java_security_AccessControlContext
@@ -3403,6 +3398,7 @@
   java_lang_invoke_LambdaForm::compute_offsets();
   java_lang_invoke_MethodType::compute_offsets();
   java_lang_invoke_CallSite::compute_offsets();
+  java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets();
   java_security_AccessControlContext::compute_offsets();
   // Initialize reflection classes. The layouts of these classes
   // changed with the new reflection implementation in JDK 1.4, and
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1170,8 +1170,6 @@
 private:
   static int _target_offset;
   static int _context_offset;
-  static int _default_context_offset;
-
 
   static void compute_offsets();
 
@@ -1181,11 +1179,7 @@
   static void         set_target(          oop site, oop target);
   static void         set_target_volatile( oop site, oop target);
 
-  static oop              context_volatile(oop site);
-  static void         set_context_volatile(oop site, oop context);
-  static bool         set_context_cas     (oop site, oop context, oop expected);
-
-  static oop default_context();
+  static oop              context(oop site);
 
   // Testers
   static bool is_subclass(Klass* klass) {
@@ -1197,6 +1191,31 @@
   static int target_offset_in_bytes()           { return _target_offset; }
 };
 
+// Interface to java.lang.invoke.MethodHandleNatives$CallSiteContext objects
+
+#define CALLSITECONTEXT_INJECTED_FIELDS(macro) \
+  macro(java_lang_invoke_MethodHandleNatives_CallSiteContext, vmdependencies, intptr_signature, false)
+
+class java_lang_invoke_MethodHandleNatives_CallSiteContext : AllStatic {
+  friend class JavaClasses;
+
+private:
+  static int _vmdependencies_offset;
+
+  static void compute_offsets();
+
+public:
+  // Accessors
+  static nmethodBucket* vmdependencies(oop context);
+  static void       set_vmdependencies(oop context, nmethodBucket* bucket);
+
+  // Testers
+  static bool is_subclass(Klass* klass) {
+    return klass->is_subclass_of(SystemDictionary::Context_klass());
+  }
+  static bool is_instance(oop obj);
+};
+
 // Interface to java.security.AccessControlContext objects
 
 class java_security_AccessControlContext: AllStatic {
@@ -1406,7 +1425,8 @@
 #define ALL_INJECTED_FIELDS(macro)          \
   CLASS_INJECTED_FIELDS(macro)              \
   CLASSLOADER_INJECTED_FIELDS(macro)        \
-  MEMBERNAME_INJECTED_FIELDS(macro)
+  MEMBERNAME_INJECTED_FIELDS(macro)         \
+  CALLSITECONTEXT_INJECTED_FIELDS(macro)
 
 // Interface to hard-coded offset checking
 
--- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -49,6 +49,10 @@
   return obj != NULL && is_subclass(obj->klass());
 }
 
+inline bool java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(oop obj) {
+  return obj != NULL && is_subclass(obj->klass());
+}
+
 inline bool java_lang_invoke_MemberName::is_instance(oop obj) {
   return obj != NULL && is_subclass(obj->klass());
 }
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -159,6 +159,7 @@
   do_klass(MethodType_klass,                            java_lang_invoke_MethodType,               Pre                 ) \
   do_klass(BootstrapMethodError_klass,                  java_lang_BootstrapMethodError,            Pre                 ) \
   do_klass(CallSite_klass,                              java_lang_invoke_CallSite,                 Pre                 ) \
+  do_klass(Context_klass,                               java_lang_invoke_MethodHandleNatives_CallSiteContext, Pre      ) \
   do_klass(ConstantCallSite_klass,                      java_lang_invoke_ConstantCallSite,         Pre                 ) \
   do_klass(MutableCallSite_klass,                       java_lang_invoke_MutableCallSite,          Pre                 ) \
   do_klass(VolatileCallSite_klass,                      java_lang_invoke_VolatileCallSite,         Pre                 ) \
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -45,6 +45,8 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
+#include "runtime/thread.hpp"
+#include "services/threadService.hpp"
 #include "utilities/bytes.hpp"
 
 #define NOFAILOVER_MAJOR_VERSION                       51
@@ -130,6 +132,16 @@
     return true;
   }
 
+  // Timer includes any side effects of class verification (resolution,
+  // etc), but not recursive calls to Verifier::verify().
+  JavaThread* jt = (JavaThread*)THREAD;
+  PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
+                           ClassLoader::perf_class_verify_selftime(),
+                           ClassLoader::perf_classes_verified(),
+                           jt->get_thread_stat()->perf_recursion_counts_addr(),
+                           jt->get_thread_stat()->perf_timers_addr(),
+                           PerfClassTraceTime::CLASS_VERIFY);
+
   // If the class should be verified, first see if we can use the split
   // verifier.  If not, or if verification fails and FailOverToOldVerifier
   // is set, then call the inference verifier.
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -274,12 +274,14 @@
   /* internal classes known only to the JVM: */                                                   \
   template(java_lang_invoke_MemberName,               "java/lang/invoke/MemberName")              \
   template(java_lang_invoke_MethodHandleNatives,      "java/lang/invoke/MethodHandleNatives")     \
+  template(java_lang_invoke_MethodHandleNatives_CallSiteContext, "java/lang/invoke/MethodHandleNatives$CallSiteContext") \
   template(java_lang_invoke_LambdaForm,               "java/lang/invoke/LambdaForm")              \
   template(java_lang_invoke_ForceInline_signature,    "Ljava/lang/invoke/ForceInline;")           \
   template(java_lang_invoke_DontInline_signature,     "Ljava/lang/invoke/DontInline;")            \
   template(java_lang_invoke_Stable_signature,         "Ljava/lang/invoke/Stable;")                \
   template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
   template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;")  \
+  template(java_lang_invoke_MethodHandleNatives_CallSiteContext_signature, "Ljava/lang/invoke/MethodHandleNatives$CallSiteContext;") \
   /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */         \
   template(findMethodHandleType_name,                 "findMethodHandleType")                     \
   template(findMethodHandleType_signature,       "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
@@ -401,7 +403,7 @@
   template(protection_domain_name,                    "protection_domain")                        \
   template(signers_name,                              "signers_name")                             \
   template(loader_data_name,                          "loader_data")                              \
-  template(dependencies_name,                         "dependencies")                             \
+  template(vmdependencies_name,                       "vmdependencies")                           \
   template(input_stream_void_signature,               "(Ljava/io/InputStream;)V")                 \
   template(getFileURL_name,                           "getFileURL")                               \
   template(getFileURL_signature,                      "(Ljava/io/File;)Ljava/net/URL;")           \
--- a/hotspot/src/share/vm/code/codeCache.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1047,40 +1047,6 @@
   }
 }
 
-// Flushes compiled methods dependent on a particular CallSite
-// instance when its target is different than the given MethodHandle.
-void CodeCache::flush_dependents_on(Handle call_site, Handle method_handle) {
-  assert_lock_strong(Compile_lock);
-
-  if (number_of_nmethods_with_dependencies() == 0) return;
-
-  // CodeCache can only be updated by a thread_in_VM and they will all be
-  // stopped during the safepoint so CodeCache will be safe to update without
-  // holding the CodeCache_lock.
-
-  CallSiteDepChange changes(call_site(), method_handle());
-
-  // Compute the dependent nmethods that have a reference to a
-  // CallSite object.  We use InstanceKlass::mark_dependent_nmethod
-  // directly instead of CodeCache::mark_for_deoptimization because we
-  // want dependents on the call site class only not all classes in
-  // the ContextStream.
-  int marked = 0;
-  {
-    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-    InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
-    if (ctxk == NULL) {
-      return; // No dependencies to invalidate yet.
-    }
-    marked = ctxk->mark_dependent_nmethods(changes);
-  }
-  if (marked > 0) {
-    // At least one nmethod has been marked for deoptimization
-    VM_Deoptimize op;
-    VMThread::execute(&op);
-  }
-}
-
 #ifdef HOTSWAP
 // Flushes compiled methods dependent on dependee in the evolutionary sense
 void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
--- a/hotspot/src/share/vm/code/codeCache.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/code/codeCache.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -224,7 +224,6 @@
 
   // Flushing and deoptimization
   static void flush_dependents_on(instanceKlassHandle dependee);
-  static void flush_dependents_on(Handle call_site, Handle method_handle);
 #ifdef HOTSWAP
   // Flushing and deoptimization in case of evolution
   static void flush_evol_dependents_on(instanceKlassHandle dependee);
--- a/hotspot/src/share/vm/code/dependencies.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/code/dependencies.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -117,9 +117,7 @@
 }
 
 void Dependencies::assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle) {
-  ciKlass* ctxk = call_site->get_context();
-  check_ctxk(ctxk);
-  assert_common_3(call_site_target_value, ctxk, call_site, method_handle);
+  assert_common_2(call_site_target_value, call_site, method_handle);
 }
 
 // Helper function.  If we are adding a new dep. under ctxk2,
@@ -175,7 +173,6 @@
       }
     }
   } else {
-    assert(dep_implicit_context_arg(dept) == 0, "sanity");
     if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) {
       // look in this bucket for redundant assertions
       const int stride = 2;
@@ -389,7 +386,7 @@
   3, // unique_concrete_subtypes_2 ctxk, k1, k2
   3, // unique_concrete_methods_2 ctxk, m1, m2
   1, // no_finalizable_subclasses ctxk
-  3  // call_site_target_value ctxk, call_site, method_handle
+  2  // call_site_target_value call_site, method_handle
 };
 
 const char* Dependencies::dep_name(Dependencies::DepType dept) {
@@ -1515,16 +1512,11 @@
   return find_finalizable_subclass(search_at);
 }
 
-Klass* Dependencies::check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) {
+Klass* Dependencies::check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes) {
+  assert(!oopDesc::is_null(call_site), "sanity");
+  assert(!oopDesc::is_null(method_handle), "sanity");
   assert(call_site->is_a(SystemDictionary::CallSite_klass()),     "sanity");
-  assert(!oopDesc::is_null(method_handle), "sanity");
 
-  Klass* call_site_ctxk = MethodHandles::get_call_site_context(call_site);
-  assert(!Klass::is_null(call_site_ctxk), "call site context should be initialized already");
-  if (recorded_ctxk != call_site_ctxk) {
-    // Stale context
-    return recorded_ctxk;
-  }
   if (changes == NULL) {
     // Validate all CallSites
     if (java_lang_invoke_CallSite::target(call_site) != method_handle)
@@ -1599,7 +1591,7 @@
   Klass* witness = NULL;
   switch (type()) {
   case call_site_target_value:
-    witness = check_call_site_target_value(context_type(), argument_oop(1), argument_oop(2), changes);
+    witness = check_call_site_target_value(argument_oop(0), argument_oop(1), changes);
     break;
   default:
     witness = NULL;
--- a/hotspot/src/share/vm/code/dependencies.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/code/dependencies.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -173,7 +173,7 @@
     non_klass_types     = (1 << call_site_target_value),
     klass_types         = all_types & ~non_klass_types,
 
-    non_ctxk_types      = (1 << evol_method),
+    non_ctxk_types      = (1 << evol_method) | (1 << call_site_target_value),
     implicit_ctxk_types = 0,
     explicit_ctxk_types = all_types & ~(non_ctxk_types | implicit_ctxk_types),
 
@@ -330,7 +330,7 @@
   static Klass* check_exclusive_concrete_methods(Klass* ctxk, Method* m1, Method* m2,
                                                    KlassDepChange* changes = NULL);
   static Klass* check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes = NULL);
-  static Klass* check_call_site_target_value(Klass* recorded_ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
+  static Klass* check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
   // A returned Klass* is NULL if the dependency assertion is still
   // valid.  A non-NULL Klass* is a 'witness' to the assertion
   // failure, a point in the class hierarchy where the assertion has
@@ -496,7 +496,7 @@
     bool next();
 
     DepType type()               { return _type; }
-    bool is_oop_argument(int i)  { return type() == call_site_target_value && i > 0; }
+    bool is_oop_argument(int i)  { return type() == call_site_target_value; }
     uintptr_t get_identifier(int i);
 
     int argument_count()         { return dep_args(type()); }
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -565,13 +565,18 @@
       // the number of methods compiled.  For applications with a lot
       // classes the slow way is too slow.
       for (Dependencies::DepStream deps(nm); deps.next(); ) {
-        Klass* klass = deps.context_type();
-        if (klass == NULL) {
-          continue;  // ignore things like evol_method
+        if (deps.type() == Dependencies::call_site_target_value) {
+          // CallSite dependencies are managed on per-CallSite instance basis.
+          oop call_site = deps.argument_oop(0);
+          MethodHandles::add_dependent_nmethod(call_site, nm);
+        } else {
+          Klass* klass = deps.context_type();
+          if (klass == NULL) {
+            continue;  // ignore things like evol_method
+          }
+          // record this nmethod as dependent on this klass
+          InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
         }
-
-        // record this nmethod as dependent on this klass
-        InstanceKlass::cast(klass)->add_dependent_nmethod(nm);
       }
       NOT_PRODUCT(nmethod_stats.note_nmethod(nm));
       if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
@@ -1464,13 +1469,20 @@
   if (!has_flushed_dependencies()) {
     set_has_flushed_dependencies();
     for (Dependencies::DepStream deps(this); deps.next(); ) {
-      Klass* klass = deps.context_type();
-      if (klass == NULL)  continue;  // ignore things like evol_method
-
-      // During GC the is_alive closure is non-NULL, and is used to
-      // determine liveness of dependees that need to be updated.
-      if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
-        InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
+      if (deps.type() == Dependencies::call_site_target_value) {
+        // CallSite dependencies are managed on per-CallSite instance basis.
+        oop call_site = deps.argument_oop(0);
+        MethodHandles::remove_dependent_nmethod(call_site, this);
+      } else {
+        Klass* klass = deps.context_type();
+        if (klass == NULL) {
+          continue;  // ignore things like evol_method
+        }
+        // During GC the is_alive closure is non-NULL, and is used to
+        // determine liveness of dependees that need to be updated.
+        if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
+          InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
+        }
       }
     }
   }
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -254,9 +254,9 @@
   if (_gc_cause != GCCause::_gc_locker &&
       gch->total_full_collections_completed() <= _full_gc_count_before) {
     // maybe we should change the condition to test _gc_cause ==
-    // GCCause::_java_lang_system_gc, instead of
-    // _gc_cause != GCCause::_gc_locker
-    assert(_gc_cause == GCCause::_java_lang_system_gc,
+    // GCCause::_java_lang_system_gc or GCCause::_dcmd_gc_run,
+    // instead of _gc_cause != GCCause::_gc_locker
+    assert(GCCause::is_user_requested_gc(_gc_cause),
            "the only way to get here if this was a System.gc()-induced GC");
     assert(ExplicitGCInvokesConcurrent, "Error");
     // Now, wait for witnessing concurrent gc cycle to complete,
--- a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -43,7 +43,7 @@
 }
 
 // Run a task; returns when the task is done, or the workers yield,
-// or the task is aborted, or the work gang is terminated via stop().
+// or the task is aborted.
 // A task that has been yielded can be continued via this interface
 // by using the same task repeatedly as the argument to the call.
 // It is expected that the YieldingFlexibleGangTask carries the appropriate
@@ -297,16 +297,9 @@
   WorkData data;
   int id;
   while (true) {
-    // Check if there is work to do or if we have been asked
-    // to terminate
+    // Check if there is work to do.
     gang()->internal_worker_poll(&data);
-    if (data.terminate()) {
-      // We have been asked to terminate.
-      assert(gang()->task() == NULL, "No task binding");
-      // set_status(TERMINATED);
-      return;
-    } else if (data.task() != NULL &&
-               data.sequence_number() != previous_sequence_number) {
+    if (data.task() != NULL && data.sequence_number() != previous_sequence_number) {
       // There is work to be done.
       // First check if we need to become active or if there
       // are already the requisite number of workers
--- a/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/cms/yieldingWorkgroup.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -176,7 +176,7 @@
   GangWorker* allocate_worker(uint which);
 
   // Run a task; returns when the task is done, or the workers yield,
-  // or the task is aborted, or the work gang is terminated via stop().
+  // or the task is aborted.
   // A task that has been yielded can be continued via this same interface
   // by using the same task repeatedly as the argument to the call.
   // It is expected that the YieldingFlexibleGangTask carries the appropriate
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1183,7 +1183,7 @@
     IsGCActiveMark x;
 
     // Timing
-    assert(gc_cause() != GCCause::_java_lang_system_gc || explicit_gc, "invariant");
+    assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant");
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
     {
@@ -2199,6 +2199,7 @@
   switch (cause) {
     case GCCause::_gc_locker:               return GCLockerInvokesConcurrent;
     case GCCause::_java_lang_system_gc:     return ExplicitGCInvokesConcurrent;
+    case GCCause::_dcmd_gc_run:             return ExplicitGCInvokesConcurrent;
     case GCCause::_g1_humongous_allocation: return true;
     case GCCause::_update_allocation_context_stats_inc: return true;
     case GCCause::_wb_conc_mark:            return true;
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -324,7 +324,8 @@
   // explicitly started if:
   // (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or
   // (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent.
-  // (c) cause == _g1_humongous_allocation
+  // (c) cause == _dcmd_gc_run and +ExplicitGCInvokesConcurrent.
+  // (d) cause == _g1_humongous_allocation
   bool should_do_concurrent_full_gc(GCCause::Cause cause);
 
   // Keeps track of how many "old marking cycles" (i.e., Full GCs or
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -168,7 +168,7 @@
   // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
   // that just started (or maybe one that was already in progress) to
   // finish.
-  if (_gc_cause == GCCause::_java_lang_system_gc &&
+  if (GCCause::is_user_requested_gc(_gc_cause) &&
       _should_initiate_conc_mark) {
     assert(ExplicitGCInvokesConcurrent,
            "the only way to be here is if ExplicitGCInvokesConcurrent is set");
--- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -130,7 +130,7 @@
   // Update the pause time.
   _major_timer.stop();
 
-  if (gc_cause != GCCause::_java_lang_system_gc ||
+  if (!GCCause::is_user_requested_gc(gc_cause) ||
       UseAdaptiveSizePolicyWithSystemGC) {
     double major_pause_in_seconds = _major_timer.seconds();
     double major_pause_in_ms = major_pause_in_seconds * MILLIUNITS;
--- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -272,7 +272,7 @@
       // Don't check if the size_policy is ready here.  Let
       // the size_policy check that internally.
       if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
-          ((gc_cause != GCCause::_java_lang_system_gc) ||
+          (!GCCause::is_user_requested_gc(gc_cause) ||
             UseAdaptiveSizePolicyWithSystemGC)) {
         // Swap the survivor spaces if from_space is empty. The
         // resize_young_gen() called below is normally used after
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -2053,7 +2053,7 @@
     marking_phase(vmthread_cm, maximum_heap_compaction, &_gc_tracer);
 
     bool max_on_system_gc = UseMaximumCompactionOnSystemGC
-      && gc_cause == GCCause::_java_lang_system_gc;
+      && GCCause::is_user_requested_gc(gc_cause);
     summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
 
     COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity"));
@@ -2089,7 +2089,7 @@
       // Don't check if the size_policy is ready here.  Let
       // the size_policy check that internally.
       if (UseAdaptiveGenerationSizePolicyAtMajorCollection &&
-          ((gc_cause != GCCause::_java_lang_system_gc) ||
+          (!GCCause::is_user_requested_gc(gc_cause) ||
             UseAdaptiveSizePolicyWithSystemGC)) {
         // Swap the survivor spaces if from_space is empty. The
         // resize_young_gen() called below is normally used after
--- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -290,7 +290,7 @@
 
   AdaptiveSizePolicyOutput(size_policy, heap->total_collections());
 
-  if ((gc_cause != GCCause::_java_lang_system_gc) ||
+  if (!GCCause::is_user_requested_gc(gc_cause) ||
        UseAdaptiveSizePolicyWithSystemGC) {
     // Gather the feedback data for eden occupancy.
     young_gen->eden_space()->accumulate_statistics();
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -960,7 +960,7 @@
                             GCCause::to_string(gch->gc_cause()));
       }
       assert(gch->gc_cause() == GCCause::_scavenge_alot ||
-             (gch->gc_cause() == GCCause::_java_lang_system_gc && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
+             (GCCause::is_user_requested_gc(gch->gc_cause()) && UseConcMarkSweepGC && ExplicitGCInvokesConcurrent) ||
              !gch->incremental_collection_failed(),
              "Twice in a row");
       seen_incremental_collection_failed = false;
--- a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -244,7 +244,7 @@
   // Update the pause time.
   _minor_timer.stop();
 
-  if (gc_cause != GCCause::_java_lang_system_gc ||
+  if (!GCCause::is_user_requested_gc(gc_cause) ||
       UseAdaptiveSizePolicyWithSystemGC) {
     double minor_pause_in_seconds = _minor_timer.seconds();
     double minor_pause_in_ms = minor_pause_in_seconds * MILLIUNITS;
--- a/hotspot/src/share/vm/gc/shared/gcCause.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcCause.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -103,6 +103,9 @@
     case _last_ditch_collection:
       return "Last ditch collection";
 
+    case _dcmd_gc_run:
+      return "Diagnostic Command";
+
     case _last_gc_cause:
       return "ILLEGAL VALUE - last gc cause - ILLEGAL VALUE";
 
--- a/hotspot/src/share/vm/gc/shared/gcCause.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/gcCause.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -74,12 +74,15 @@
     _g1_humongous_allocation,
 
     _last_ditch_collection,
+
+    _dcmd_gc_run,
+
     _last_gc_cause
   };
 
   inline static bool is_user_requested_gc(GCCause::Cause cause) {
     return (cause == GCCause::_java_lang_system_gc ||
-            cause == GCCause::_jvmti_force_gc);
+            cause == GCCause::_dcmd_gc_run);
   }
 
   inline static bool is_serviceability_requested_gc(GCCause::Cause
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -304,9 +304,16 @@
 }
 
 bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
-  return UseConcMarkSweepGC &&
-         ((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
-          (cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
+  if (!UseConcMarkSweepGC) {
+    return false;
+  }
+
+  switch (cause) {
+    case GCCause::_gc_locker:           return GCLockerInvokesConcurrent;
+    case GCCause::_java_lang_system_gc:
+    case GCCause::_dcmd_gc_run:         return ExplicitGCInvokesConcurrent;
+    default:                            return false;
+  }
 }
 
 void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t size,
--- a/hotspot/src/share/vm/gc/shared/workgroup.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -47,7 +47,6 @@
                          /* allow_vm_block */ are_GC_task_threads,
                                               Monitor::_safepoint_check_sometimes);
   assert(monitor() != NULL, "Failed to allocate monitor");
-  _terminate = false;
   _task = NULL;
   _sequence_number = 0;
   _started_workers = 0;
@@ -106,18 +105,6 @@
   return true;
 }
 
-AbstractWorkGang::~AbstractWorkGang() {
-  if (TraceWorkGang) {
-    tty->print_cr("Destructing work gang %s", name());
-  }
-  stop();   // stop all the workers
-  for (uint worker = 0; worker < total_workers(); worker += 1) {
-    delete gang_worker(worker);
-  }
-  delete gang_workers();
-  delete monitor();
-}
-
 GangWorker* AbstractWorkGang::gang_worker(uint i) const {
   // Array index bounds checking.
   GangWorker* result = NULL;
@@ -175,28 +162,9 @@
   WorkGang::run_task(task, (uint) active_workers());
 }
 
-void AbstractWorkGang::stop() {
-  // Tell all workers to terminate, then wait for them to become inactive.
-  MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
-  if (TraceWorkGang) {
-    tty->print_cr("Stopping work gang %s task %s", name(), task()->name());
-  }
-  _task = NULL;
-  _terminate = true;
-  monitor()->notify_all();
-  while (finished_workers() < active_workers()) {
-    if (TraceWorkGang) {
-      tty->print_cr("Waiting in work gang %s: %u/%u finished",
-                    name(), finished_workers(), active_workers());
-    }
-    monitor()->wait(/* no_safepoint_check */ true);
-  }
-}
-
 void AbstractWorkGang::internal_worker_poll(WorkData* data) const {
   assert(monitor()->owned_by_self(), "worker_poll is an internal method");
   assert(data != NULL, "worker data is null");
-  data->set_terminate(terminate());
   data->set_task(task());
   data->set_sequence_number(sequence_number());
 }
@@ -259,7 +227,7 @@
 void GangWorker::loop() {
   int previous_sequence_number = 0;
   Monitor* gang_monitor = gang()->monitor();
-  for ( ; /* !terminate() */; ) {
+  for ( ; ; ) {
     WorkData data;
     int part;  // Initialized below.
     {
@@ -272,8 +240,6 @@
       if (TraceWorkGang) {
         tty->print("Polled outside for work in gang %s worker %u",
                    gang()->name(), id());
-        tty->print("  terminate: %s",
-                   data.terminate() ? "true" : "false");
         tty->print("  sequence: %d (prev: %d)",
                    data.sequence_number(), previous_sequence_number);
         if (data.task() != NULL) {
@@ -283,13 +249,7 @@
         }
         tty->cr();
       }
-      for ( ; /* break or return */; ) {
-        // Terminate if requested.
-        if (data.terminate()) {
-          gang()->internal_note_finish();
-          gang_monitor->notify_all();
-          return;
-        }
+      for ( ; /* break */; ) {
         // Check for new work.
         if ((data.task() != NULL) &&
             (data.sequence_number() != previous_sequence_number)) {
@@ -306,8 +266,6 @@
         if (TraceWorkGang) {
           tty->print("Polled inside for work in gang %s worker %u",
                      gang()->name(), id());
-          tty->print("  terminate: %s",
-                     data.terminate() ? "true" : "false");
           tty->print("  sequence: %d (prev: %d)",
                      data.sequence_number(), previous_sequence_number);
           if (data.task() != NULL) {
--- a/hotspot/src/share/vm/gc/shared/workgroup.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -103,16 +103,15 @@
 // An abstract class representing a gang of workers.
 // You subclass this to supply an implementation of run_task().
 class AbstractWorkGang: public CHeapObj<mtInternal> {
-  // Here's the public interface to this class.
+protected:
+  // Work gangs are never deleted, so no need to cleanup.
+  ~AbstractWorkGang() { ShouldNotReachHere(); }
 public:
-  // Constructor and destructor.
+  // Constructor.
   AbstractWorkGang(const char* name, bool are_GC_task_threads,
                    bool are_ConcurrentGC_threads);
-  ~AbstractWorkGang();
   // Run a task, returns when the task is done (or terminated).
   virtual void run_task(AbstractGangTask* task) = 0;
-  // Stop and terminate all workers.
-  virtual void stop();
   // Return true if more workers should be applied to the task.
   virtual bool needs_more_workers() const { return true; }
 public:
@@ -129,8 +128,6 @@
   Monitor*  _monitor;
   // The count of the number of workers in the gang.
   uint _total_workers;
-  // Whether the workers should terminate.
-  bool _terminate;
   // The array of worker threads for this gang.
   // This is only needed for cleaning up.
   GangWorker** _gang_workers;
@@ -153,9 +150,6 @@
   virtual uint active_workers() const {
     return _total_workers;
   }
-  bool terminate() const {
-    return _terminate;
-  }
   GangWorker** gang_workers() const {
     return _gang_workers;
   }
@@ -205,21 +199,16 @@
 class WorkData: public StackObj {
   // This would be a struct, but I want accessor methods.
 private:
-  bool              _terminate;
   AbstractGangTask* _task;
   int               _sequence_number;
 public:
   // Constructor and destructor
   WorkData() {
-    _terminate       = false;
     _task            = NULL;
     _sequence_number = 0;
   }
   ~WorkData() {
   }
-  // Accessors and modifiers
-  bool terminate()                       const { return _terminate;  }
-  void set_terminate(bool value)               { _terminate = value; }
   AbstractGangTask* task()               const { return _task; }
   void set_task(AbstractGangTask* value)       { _task = value; }
   int sequence_number()                  const { return _sequence_number; }
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, 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
@@ -147,13 +147,10 @@
 
 
 methodHandle Bytecode_invoke::static_target(TRAPS) {
-  methodHandle m;
-  KlassHandle resolved_klass;
   constantPoolHandle constants(THREAD, this->constants());
 
   Bytecodes::Code bc = invoke_code();
-  LinkResolver::resolve_method_statically(m, resolved_klass, bc, constants, index(), CHECK_(methodHandle()));
-  return m;
+  return LinkResolver::resolve_method_statically(bc, constants, index(), THREAD);
 }
 
 Handle Bytecode_invoke::appendix(TRAPS) {
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -52,13 +52,17 @@
 // Implementation of CallInfo
 
 
-void CallInfo::set_static(KlassHandle resolved_klass, methodHandle resolved_method, TRAPS) {
+void CallInfo::set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS) {
   int vtable_index = Method::nonvirtual_vtable_index;
   set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK);
 }
 
 
-void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index, TRAPS) {
+void CallInfo::set_interface(KlassHandle resolved_klass,
+                             KlassHandle selected_klass,
+                             const methodHandle& resolved_method,
+                             const methodHandle& selected_method,
+                             int itable_index, TRAPS) {
   // This is only called for interface methods. If the resolved_method
   // comes from java/lang/Object, it can be the subject of a virtual call, so
   // we should pick the vtable index from the resolved method.
@@ -68,7 +72,11 @@
   set_common(resolved_klass, selected_klass, resolved_method, selected_method, CallInfo::itable_call, itable_index, CHECK);
 }
 
-void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) {
+void CallInfo::set_virtual(KlassHandle resolved_klass,
+                           KlassHandle selected_klass,
+                           const methodHandle& resolved_method,
+                           const methodHandle& selected_method,
+                           int vtable_index, TRAPS) {
   assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, "valid index");
   assert(vtable_index < 0 || !resolved_method->has_vtable_index() || vtable_index == resolved_method->vtable_index(), "");
   CallKind kind = (vtable_index >= 0 && !resolved_method->can_be_statically_bound() ? CallInfo::vtable_call : CallInfo::direct_call);
@@ -76,7 +84,9 @@
   assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call");
 }
 
-void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS) {
+void CallInfo::set_handle(const methodHandle& resolved_method,
+                          Handle resolved_appendix,
+                          Handle resolved_method_type, TRAPS) {
   if (resolved_method.is_null()) {
     THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null");
   }
@@ -93,8 +103,8 @@
 
 void CallInfo::set_common(KlassHandle resolved_klass,
                           KlassHandle selected_klass,
-                          methodHandle resolved_method,
-                          methodHandle selected_method,
+                          const methodHandle& resolved_method,
+                          const methodHandle& selected_method,
                           CallKind kind,
                           int index,
                           TRAPS) {
@@ -210,8 +220,52 @@
 }
 #endif //ASSERT
 
+#ifndef PRODUCT
+void CallInfo::print() {
+  ResourceMark rm;
+  const char* kindstr = "unknown";
+  switch (_call_kind) {
+  case direct_call: kindstr = "direct"; break;
+  case vtable_call: kindstr = "vtable"; break;
+  case itable_call: kindstr = "itable"; break;
+  }
+  tty->print_cr("Call %s@%d %s", kindstr, _call_index,
+                _resolved_method.is_null() ? "(none)" : _resolved_method->name_and_sig_as_C_string());
+}
+#endif
 
+//------------------------------------------------------------------------------------------------------------------------
+// Implementation of LinkInfo
 
+LinkInfo::LinkInfo(constantPoolHandle pool, int index, TRAPS) {
+   // resolve klass
+  Klass* result = pool->klass_ref_at(index, CHECK);
+  _resolved_klass = KlassHandle(THREAD, result);
+
+  // Get name, signature, and static klass
+  _name          = pool->name_ref_at(index);
+  _signature     = pool->signature_ref_at(index);
+  _current_klass = KlassHandle(THREAD, pool->pool_holder());
+
+  // Coming from the constant pool always checks access
+  _check_access  = true;
+}
+
+char* LinkInfo::method_string() const {
+  return Method::name_and_sig_as_C_string(_resolved_klass(), _name, _signature);
+}
+
+#ifndef PRODUCT
+void LinkInfo::print() {
+  ResourceMark rm;
+  tty->print_cr("Link resolved_klass=%s name=%s signature=%s current_klass=%s check_access=%s",
+                _resolved_klass->name()->as_C_string(),
+                _name->as_C_string(),
+                _signature->as_C_string(),
+                _current_klass.is_null() ? "(none)" : _current_klass->name()->as_C_string(),
+                _check_access ? "true" : "false");
+}
+#endif // PRODUCT
 //------------------------------------------------------------------------------------------------------------------------
 // Klass resolution
 
@@ -231,11 +285,6 @@
   }
 }
 
-void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, int index, TRAPS) {
-  Klass* result_oop = pool->klass_ref_at(index, CHECK);
-  result = KlassHandle(THREAD, result_oop);
-}
-
 //------------------------------------------------------------------------------------------------------------------------
 // Method resolution
 //
@@ -243,76 +292,84 @@
 
 // Look up method in klasses, including static methods
 // Then look up local default methods
-void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) {
+methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info,
+                                                    bool checkpolymorphism,
+                                                    bool in_imethod_resolve, TRAPS) {
+  KlassHandle klass = link_info.resolved_klass();
+  Symbol* name = link_info.name();
+  Symbol* signature = link_info.signature();
+
   // Ignore overpasses so statics can be found during resolution
-  Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass);
+  Method* result = klass->uncached_lookup_method(name, signature, Klass::skip_overpass);
 
   if (klass->oop_is_array()) {
     // Only consider klass and super klass for arrays
-    result = methodHandle(THREAD, result_oop);
-    return;
+    return methodHandle(THREAD, result);
   }
 
   // JDK 8, JVMS 5.4.3.4: Interface method resolution should
   // ignore static and non-public methods of java.lang.Object,
   // like clone, finalize, registerNatives.
   if (in_imethod_resolve &&
-      result_oop != NULL &&
+      result != NULL &&
       klass->is_interface() &&
-      (result_oop->is_static() || !result_oop->is_public()) &&
-      result_oop->method_holder() == SystemDictionary::Object_klass()) {
-    result_oop = NULL;
+      (result->is_static() || !result->is_public()) &&
+      result->method_holder() == SystemDictionary::Object_klass()) {
+    result = NULL;
   }
 
   // Before considering default methods, check for an overpass in the
   // current class if a method has not been found.
-  if (result_oop == NULL) {
-    result_oop = InstanceKlass::cast(klass())->find_method(name, signature);
+  if (result == NULL) {
+    result = InstanceKlass::cast(klass())->find_method(name, signature);
   }
 
-  if (result_oop == NULL) {
+  if (result == NULL) {
     Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
     if (default_methods != NULL) {
-      result_oop = InstanceKlass::find_method(default_methods, name, signature);
+      result = InstanceKlass::find_method(default_methods, name, signature);
     }
   }
 
-  if (checkpolymorphism && result_oop != NULL) {
-    vmIntrinsics::ID iid = result_oop->intrinsic_id();
+  if (checkpolymorphism && result != NULL) {
+    vmIntrinsics::ID iid = result->intrinsic_id();
     if (MethodHandles::is_signature_polymorphic(iid)) {
       // Do not link directly to these.  The VM must produce a synthetic one using lookup_polymorphic_method.
-      return;
+      return NULL;
     }
   }
-  result = methodHandle(THREAD, result_oop);
+  return methodHandle(THREAD, result);
 }
 
 // returns first instance method
 // Looks up method in classes, then looks up local default methods
-void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
-  Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::find_overpass);
-  result = methodHandle(THREAD, result_oop);
-  while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) {
-    KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super());
-    result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::find_overpass));
+methodHandle LinkResolver::lookup_instance_method_in_klasses(KlassHandle klass,
+                                                             Symbol* name,
+                                                             Symbol* signature, TRAPS) {
+  Method* result = klass->uncached_lookup_method(name, signature, Klass::find_overpass);
+
+  while (result != NULL && result->is_static() && result->method_holder()->super() != NULL) {
+    Klass* super_klass = result->method_holder()->super();
+    result = super_klass->uncached_lookup_method(name, signature, Klass::find_overpass);
   }
 
   if (klass->oop_is_array()) {
     // Only consider klass and super klass for arrays
-    return;
+    return methodHandle(THREAD, result);
   }
 
-  if (result.is_null()) {
+  if (result == NULL) {
     Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
     if (default_methods != NULL) {
-      result = methodHandle(InstanceKlass::find_method(default_methods, name, signature));
-      assert(result.is_null() || !result->is_static(), "static defaults not allowed");
+      result = InstanceKlass::find_method(default_methods, name, signature);
+      assert(result == NULL || !result->is_static(), "static defaults not allowed");
     }
   }
+  return methodHandle(THREAD, result);
 }
 
 int LinkResolver::vtable_index_of_interface_method(KlassHandle klass,
-                                          methodHandle resolved_method) {
+                                                   const methodHandle& resolved_method) {
 
   int vtable_index = Method::invalid_vtable_index;
   Symbol* name = resolved_method->name();
@@ -336,21 +393,26 @@
   return vtable_index;
 }
 
-void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
-  InstanceKlass *ik = InstanceKlass::cast(klass());
+methodHandle LinkResolver::lookup_method_in_interfaces(const LinkInfo& cp_info, TRAPS) {
+  InstanceKlass *ik = InstanceKlass::cast(cp_info.resolved_klass()());
 
   // Specify 'true' in order to skip default methods when searching the
   // interfaces.  Function lookup_method_in_klasses() already looked for
   // the method in the default methods table.
-  result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, Klass::skip_defaults));
+  return methodHandle(THREAD,
+    ik->lookup_method_in_all_interfaces(cp_info.name(), cp_info.signature(),
+    Klass::skip_defaults));
 }
 
-void LinkResolver::lookup_polymorphic_method(methodHandle& result,
-                                             KlassHandle klass, Symbol* name, Symbol* full_signature,
-                                             KlassHandle current_klass,
+methodHandle LinkResolver::lookup_polymorphic_method(
+                                             const LinkInfo& link_info,
                                              Handle *appendix_result_or_null,
                                              Handle *method_type_result,
                                              TRAPS) {
+  KlassHandle klass = link_info.resolved_klass();
+  Symbol* name = link_info.name();
+  Symbol* full_signature = link_info.signature();
+
   vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
   if (TraceMethodHandles) {
     ResourceMark rm(THREAD);
@@ -365,7 +427,7 @@
       // Do not erase last argument type (MemberName) if it is a static linkTo method.
       bool keep_last_arg = MethodHandles::is_signature_polymorphic_static(iid);
       TempNewSymbol basic_signature =
-        MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK);
+        MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK_NULL);
       if (TraceMethodHandles) {
         ResourceMark rm(THREAD);
         tty->print_cr("lookup_polymorphic_method %s %s => basic %s",
@@ -373,9 +435,9 @@
                       full_signature->as_C_string(),
                       basic_signature->as_C_string());
       }
-      result = SystemDictionary::find_method_handle_intrinsic(iid,
+      methodHandle result = SystemDictionary::find_method_handle_intrinsic(iid,
                                                               basic_signature,
-                                                              CHECK);
+                                                              CHECK_NULL);
       if (result.not_null()) {
         assert(result->is_method_handle_intrinsic(), "MH.invokeBasic or MH.linkTo* intrinsic");
         assert(result->intrinsic_id() != vmIntrinsics::_invokeGeneric, "wrong place to find this");
@@ -384,8 +446,8 @@
           tty->print("lookup_polymorphic_method => intrinsic ");
           result->print_on(tty);
         }
-        return;
       }
+      return result;
     } else if (iid == vmIntrinsics::_invokeGeneric
                && !THREAD->is_Compiler_thread()
                && appendix_result_or_null != NULL) {
@@ -399,18 +461,19 @@
                                             Handle(),
                                             Handle(),
                                             true,
-                                            CHECK);
+                                            CHECK_NULL);
         }
       }
 
       Handle appendix;
       Handle method_type;
-      result = SystemDictionary::find_method_handle_invoker(name,
+      methodHandle result = SystemDictionary::find_method_handle_invoker(
+                                                            name,
                                                             full_signature,
-                                                            current_klass,
+                                                            link_info.current_klass(),
                                                             &appendix,
                                                             &method_type,
-                                                            CHECK);
+                                                            CHECK_NULL);
       if (TraceMethodHandles) {
         tty->print("lookup_polymorphic_method => (via Java) ");
         result->print_on(tty);
@@ -423,7 +486,7 @@
         ResourceMark rm(THREAD);
 
         TempNewSymbol basic_signature =
-          MethodHandles::lookup_basic_type_signature(full_signature, CHECK);
+          MethodHandles::lookup_basic_type_signature(full_signature, CHECK_NULL);
         int actual_size_of_params = result->size_of_parameters();
         int expected_size_of_params = ArgumentSizeComputer(basic_signature).size();
         // +1 for MethodHandle.this, +1 for trailing MethodType
@@ -441,16 +504,17 @@
         assert(appendix_result_or_null != NULL, "");
         (*appendix_result_or_null) = appendix;
         (*method_type_result)      = method_type;
-        return;
       }
+      return result;
     }
   }
+  return NULL;
 }
 
 void LinkResolver::check_method_accessability(KlassHandle ref_klass,
                                               KlassHandle resolved_klass,
                                               KlassHandle sel_klass,
-                                              methodHandle sel_method,
+                                              const methodHandle& sel_method,
                                               TRAPS) {
 
   AccessFlags flags = sel_method->access_flags();
@@ -493,8 +557,8 @@
   }
 }
 
-void LinkResolver::resolve_method_statically(methodHandle& resolved_method, KlassHandle& resolved_klass,
-                                             Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS) {
+methodHandle LinkResolver::resolve_method_statically(Bytecodes::Code code,
+                                                     constantPoolHandle pool, int index, TRAPS) {
   // This method is used only
   // (1) in C2 from InlineTree::ok_to_inline (via ciMethod::check_call),
   // and
@@ -502,49 +566,108 @@
   // It appears to fail when applied to an invokeinterface call site.
   // FIXME: Remove this method and ciMethod::check_call; refactor to use the other LinkResolver entry points.
   // resolve klass
+  KlassHandle resolved_klass;
   if (code == Bytecodes::_invokedynamic) {
     resolved_klass = SystemDictionary::MethodHandle_klass();
     Symbol* method_name = vmSymbols::invoke_name();
     Symbol* method_signature = pool->signature_ref_at(index);
     KlassHandle  current_klass(THREAD, pool->pool_holder());
-    resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK);
-    return;
+    LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass);
+    return resolve_method(link_info, /*require_methodref*/false, THREAD);
   }
 
-  resolve_klass(resolved_klass, pool, index, CHECK);
-
-  Symbol*  method_name       = pool->name_ref_at(index);
-  Symbol*  method_signature  = pool->signature_ref_at(index);
-  KlassHandle  current_klass(THREAD, pool->pool_holder());
+  LinkInfo link_info(pool, index, CHECK_NULL);
+  resolved_klass = link_info.resolved_klass();
 
   if (pool->has_preresolution()
       || (resolved_klass() == SystemDictionary::MethodHandle_klass() &&
-          MethodHandles::is_signature_polymorphic_name(resolved_klass(), method_name))) {
-    Method* result_oop = ConstantPool::method_at_if_loaded(pool, index);
-    if (result_oop != NULL) {
-      resolved_method = methodHandle(THREAD, result_oop);
-      return;
+          MethodHandles::is_signature_polymorphic_name(resolved_klass(), link_info.name()))) {
+    Method* result = ConstantPool::method_at_if_loaded(pool, index);
+    if (result != NULL) {
+      return methodHandle(THREAD, result);
     }
   }
 
   if (code == Bytecodes::_invokeinterface) {
-    resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+    return resolve_interface_method(link_info, true, THREAD);
   } else if (code == Bytecodes::_invokevirtual) {
-    resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+    return resolve_method(link_info, /*require_methodref*/true, THREAD);
   } else if (!resolved_klass->is_interface()) {
-    resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK);
+    return resolve_method(link_info, /*require_methodref*/false, THREAD);
   } else {
     bool nostatics = (code == Bytecodes::_invokestatic) ? false : true;
-    resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, nostatics, CHECK);
+    return resolve_interface_method(link_info, nostatics, THREAD);
   }
 }
 
-void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass,
-                                  Symbol* method_name, Symbol* method_signature,
-                                  KlassHandle current_klass, bool check_access,
-                                  bool require_methodref, TRAPS) {
+// Check and print a loader constraint violation message for method or interface method
+void LinkResolver::check_method_loader_constraints(const LinkInfo& link_info,
+                                                   const methodHandle& resolved_method,
+                                                   const char* method_type, TRAPS) {
+  Handle current_loader(THREAD, link_info.current_klass()->class_loader());
+  Handle resolved_loader(THREAD, resolved_method->method_holder()->class_loader());
+
+  ResourceMark rm(THREAD);
+  Symbol* failed_type_symbol =
+    SystemDictionary::check_signature_loaders(link_info.signature(), current_loader,
+                                              resolved_loader, true, CHECK);
+  if (failed_type_symbol != NULL) {
+    const char* msg = "loader constraint violation: when resolving %s"
+      " \"%s\" the class loader (instance of %s) of the current class, %s,"
+      " and the class loader (instance of %s) for the method's defining class, %s, have"
+      " different Class objects for the type %s used in the signature";
+    char* sig = link_info.method_string();
+    const char* loader1_name = SystemDictionary::loader_name(current_loader());
+    char* current = link_info.current_klass()->name()->as_C_string();
+    const char* loader2_name = SystemDictionary::loader_name(resolved_loader());
+    char* target = resolved_method->method_holder()->name()->as_C_string();
+    char* failed_type_name = failed_type_symbol->as_C_string();
+    size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1_name) +
+      strlen(current) + strlen(loader2_name) + strlen(target) +
+      strlen(failed_type_name) + strlen(method_type) + 1;
+    char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
+    jio_snprintf(buf, buflen, msg, method_type, sig, loader1_name, current, loader2_name,
+                 target, failed_type_name);
+    THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
+  }
+}
+
+void LinkResolver::check_field_loader_constraints(Symbol* field, Symbol* sig,
+                                                  KlassHandle current_klass,
+                                                  KlassHandle sel_klass, TRAPS) {
+  Handle ref_loader(THREAD, current_klass->class_loader());
+  Handle sel_loader(THREAD, sel_klass->class_loader());
+
+  ResourceMark rm(THREAD);  // needed for check_signature_loaders
+  Symbol* failed_type_symbol =
+    SystemDictionary::check_signature_loaders(sig,
+                                              ref_loader, sel_loader,
+                                              false,
+                                              CHECK);
+  if (failed_type_symbol != NULL) {
+    const char* msg = "loader constraint violation: when resolving field"
+      " \"%s\" the class loader (instance of %s) of the referring class, "
+      "%s, and the class loader (instance of %s) for the field's resolved "
+      "type, %s, have different Class objects for that type";
+    char* field_name = field->as_C_string();
+    const char* loader1_name = SystemDictionary::loader_name(ref_loader());
+    char* sel = sel_klass->name()->as_C_string();
+    const char* loader2_name = SystemDictionary::loader_name(sel_loader());
+    char* failed_type_name = failed_type_symbol->as_C_string();
+    size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1_name) +
+                    strlen(sel) + strlen(loader2_name) + strlen(failed_type_name) + 1;
+    char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
+    jio_snprintf(buf, buflen, msg, field_name, loader1_name, sel, loader2_name,
+                     failed_type_name);
+    THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
+  }
+}
+
+methodHandle LinkResolver::resolve_method(const LinkInfo& link_info,
+                                          bool require_methodref, TRAPS) {
 
   Handle nested_exception;
+  KlassHandle resolved_klass = link_info.resolved_klass();
 
   // 1. check if methodref required, that resolved_klass is not interfacemethodref
   if (require_methodref && resolved_klass->is_interface()) {
@@ -552,20 +675,19 @@
     char buf[200];
     jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected",
         resolved_klass()->external_name());
-    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+    THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
 
   // 2. lookup method in resolved klass and its super klasses
-  lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, false, CHECK);
+  methodHandle resolved_method = lookup_method_in_klasses(link_info, true, false, CHECK_NULL);
 
   if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // not found in the class hierarchy
     // 3. lookup method in all the interfaces implemented by the resolved klass
-    lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
+    resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
 
     if (resolved_method.is_null()) {
       // JSR 292:  see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc
-      lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature,
-                                current_klass, (Handle*)NULL, (Handle*)NULL, THREAD);
+      resolved_method = lookup_polymorphic_method(link_info, (Handle*)NULL, (Handle*)NULL, THREAD);
       if (HAS_PENDING_EXCEPTION) {
         nested_exception = Handle(THREAD, PENDING_EXCEPTION);
         CLEAR_PENDING_EXCEPTION;
@@ -576,15 +698,16 @@
   if (resolved_method.is_null()) {
     // 4. method lookup failed
     ResourceMark rm(THREAD);
-    THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(),
+    THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(),
                     Method::name_and_sig_as_C_string(resolved_klass(),
-                                                            method_name,
-                                                            method_signature),
-                    nested_exception);
+                                                     link_info.name(),
+                                                     link_info.signature()),
+                    nested_exception, NULL);
   }
 
   // 5. access checks, access checking may be turned off when calling from within the VM.
-  if (check_access) {
+  KlassHandle current_klass = link_info.current_klass();
+  if (link_info.check_access()) {
     assert(current_klass.not_null() , "current_klass should not be null");
 
     // check if method can be accessed by the referring class
@@ -592,76 +715,50 @@
                                resolved_klass,
                                KlassHandle(THREAD, resolved_method->method_holder()),
                                resolved_method,
-                               CHECK);
+                               CHECK_NULL);
 
     // check loader constraints
-    Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
-    Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
-    {
-      ResourceMark rm(THREAD);
-      Symbol* failed_type_symbol =
-        SystemDictionary::check_signature_loaders(method_signature, loader,
-                                                  class_loader, true, CHECK);
-      if (failed_type_symbol != NULL) {
-        const char* msg = "loader constraint violation: when resolving method"
-          " \"%s\" the class loader (instance of %s) of the current class, %s,"
-          " and the class loader (instance of %s) for the method's defining class, %s, have"
-          " different Class objects for the type %s used in the signature";
-        char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature);
-        const char* loader1 = SystemDictionary::loader_name(loader());
-        char* current = InstanceKlass::cast(current_klass())->name()->as_C_string();
-        const char* loader2 = SystemDictionary::loader_name(class_loader());
-        char* target = InstanceKlass::cast(resolved_method->method_holder())
-                       ->name()->as_C_string();
-        char* failed_type_name = failed_type_symbol->as_C_string();
-        size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
-          strlen(current) + strlen(loader2) + strlen(target) +
-          strlen(failed_type_name) + 1;
-        char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
-        jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
-                     target, failed_type_name);
-        THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
-      }
-    }
+    check_method_loader_constraints(link_info, resolved_method, "method", CHECK_NULL);
   }
+
+  return resolved_method;
 }
 
-void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
-                                            KlassHandle resolved_klass,
-                                            Symbol* method_name,
-                                            Symbol* method_signature,
-                                            KlassHandle current_klass,
-                                            bool check_access,
-                                            bool nostatics, TRAPS) {
+methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info,
+                                                    bool nostatics, TRAPS) {
+
+  KlassHandle resolved_klass = link_info.resolved_klass();
 
   // check if klass is interface
   if (!resolved_klass->is_interface()) {
     ResourceMark rm(THREAD);
     char buf[200];
     jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name());
-    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+    THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
 
   // lookup method in this interface or its super, java.lang.Object
   // JDK8: also look for static methods
-  lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, true, CHECK);
+  methodHandle resolved_method = lookup_method_in_klasses(link_info, false, true, CHECK_NULL);
 
   if (resolved_method.is_null() && !resolved_klass->oop_is_array()) {
     // lookup method in all the super-interfaces
-    lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
+    resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
   }
 
   if (resolved_method.is_null()) {
     // no method found
     ResourceMark rm(THREAD);
-    THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
-              Method::name_and_sig_as_C_string(resolved_klass(),
-                                                      method_name,
-                                                      method_signature));
+    THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(),
+                   Method::name_and_sig_as_C_string(resolved_klass(),
+                                                    link_info.name(),
+                                                    link_info.signature()));
   }
 
-  if (check_access) {
+  if (link_info.check_access()) {
     // JDK8 adds non-public interface methods, and accessability check requirement
+    KlassHandle current_klass = link_info.current_klass();
+
     assert(current_klass.not_null() , "current_klass should not be null");
 
     // check if method can be accessed by the referring class
@@ -669,38 +766,9 @@
                                resolved_klass,
                                KlassHandle(THREAD, resolved_method->method_holder()),
                                resolved_method,
-                               CHECK);
+                               CHECK_NULL);
 
-    HandleMark hm(THREAD);
-    Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
-    Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
-    {
-      ResourceMark rm(THREAD);
-      Symbol* failed_type_symbol =
-        SystemDictionary::check_signature_loaders(method_signature, loader,
-                                                  class_loader, true, CHECK);
-      if (failed_type_symbol != NULL) {
-        const char* msg = "loader constraint violation: when resolving "
-          "interface method \"%s\" the class loader (instance of %s) of the "
-          "current class, %s, and the class loader (instance of %s) for "
-          "the method's defining class, %s, have different Class objects for the type %s "
-          "used in the signature";
-        char* sig = Method::name_and_sig_as_C_string(resolved_klass(),method_name,method_signature);
-        const char* loader1 = SystemDictionary::loader_name(loader());
-        char* current = InstanceKlass::cast(current_klass())->name()->as_C_string();
-        const char* loader2 = SystemDictionary::loader_name(class_loader());
-        char* target = InstanceKlass::cast(resolved_method->method_holder())
-                       ->name()->as_C_string();
-        char* failed_type_name = failed_type_symbol->as_C_string();
-        size_t buflen = strlen(msg) + strlen(sig) + strlen(loader1) +
-          strlen(current) + strlen(loader2) + strlen(target) +
-          strlen(failed_type_name) + 1;
-        char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
-        jio_snprintf(buf, buflen, msg, sig, loader1, current, loader2,
-                     target, failed_type_name);
-        THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
-      }
-    }
+    check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL);
   }
 
   if (nostatics && resolved_method->is_static()) {
@@ -709,28 +777,16 @@
     jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s",
                  Method::name_and_sig_as_C_string(resolved_klass(),
                  resolved_method->name(), resolved_method->signature()));
-    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+    THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
 
   if (TraceItables && Verbose) {
-    ResourceMark rm(THREAD);
-    tty->print("invokeinterface resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
-                   (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
-                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
-                   Method::name_and_sig_as_C_string(resolved_klass(),
-                                                    resolved_method->name(),
-                                                    resolved_method->signature()),
-                   resolved_method->method_holder()->internal_name()
-                  );
-    resolved_method->access_flags().print_on(tty);
-    if (resolved_method->is_default_method()) {
-      tty->print("default ");
-    }
-    if (resolved_method->is_overpass()) {
-      tty->print("overpass");
-    }
+    trace_method_resolution("invokeinterface resolved method: caller-class",
+                            link_info.current_klass(), resolved_klass, resolved_method);
     tty->cr();
   }
+
+  return resolved_method;
 }
 
 //------------------------------------------------------------------------------------------------------------------------
@@ -739,7 +795,7 @@
 void LinkResolver::check_field_accessability(KlassHandle ref_klass,
                                              KlassHandle resolved_klass,
                                              KlassHandle sel_klass,
-                                             fieldDescriptor& fd,
+                                             const fieldDescriptor& fd,
                                              TRAPS) {
   if (!Reflection::verify_field_access(ref_klass(),
                                        resolved_klass(),
@@ -759,30 +815,27 @@
   }
 }
 
-void LinkResolver::resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
-  // Load these early in case the resolve of the containing klass fails
-  Symbol* field = pool->name_ref_at(index);
-  Symbol* sig   = pool->signature_ref_at(index);
-
-  // resolve specified klass
-  KlassHandle resolved_klass;
-  resolve_klass(resolved_klass, pool, index, CHECK);
-
-  KlassHandle  current_klass(THREAD, pool->pool_holder());
-  resolve_field(result, resolved_klass, field, sig, current_klass, byte, true, true, CHECK);
+void LinkResolver::resolve_field_access(fieldDescriptor& fd, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) {
+  LinkInfo link_info(pool, index, CHECK);
+  resolve_field(fd, link_info, byte, true, CHECK);
 }
 
-void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass, Symbol* field, Symbol* sig,
-                                 KlassHandle current_klass, Bytecodes::Code byte, bool check_access, bool initialize_class,
+void LinkResolver::resolve_field(fieldDescriptor& fd,
+                                 const LinkInfo& link_info,
+                                 Bytecodes::Code byte, bool initialize_class,
                                  TRAPS) {
   assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
          byte == Bytecodes::_getfield  || byte == Bytecodes::_putfield  ||
          byte == Bytecodes::_nofast_getfield  || byte == Bytecodes::_nofast_putfield  ||
-         (byte == Bytecodes::_nop && !check_access), "bad field access bytecode");
+         (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode");
 
   bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
   bool is_put    = (byte == Bytecodes::_putfield  || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield);
   // Check if there's a resolved klass containing the field
+  KlassHandle resolved_klass = link_info.resolved_klass();
+  Symbol* field = link_info.name();
+  Symbol* sig = link_info.signature();
+
   if (resolved_klass.is_null()) {
     ResourceMark rm(THREAD);
     THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
@@ -796,11 +849,12 @@
     THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string());
   }
 
-  if (!check_access)
+  if (!link_info.check_access())
     // Access checking may be turned off when calling from within the VM.
     return;
 
   // check access
+  KlassHandle current_klass = link_info.current_klass();
   check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK);
 
   // check for errors
@@ -827,34 +881,7 @@
   }
 
   if (sel_klass() != current_klass()) {
-    HandleMark hm(THREAD);
-    Handle ref_loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
-    Handle sel_loader (THREAD, InstanceKlass::cast(sel_klass())->class_loader());
-    {
-      ResourceMark rm(THREAD);
-      Symbol* failed_type_symbol =
-        SystemDictionary::check_signature_loaders(sig,
-                                                  ref_loader, sel_loader,
-                                                  false,
-                                                  CHECK);
-      if (failed_type_symbol != NULL) {
-        const char* msg = "loader constraint violation: when resolving field"
-          " \"%s\" the class loader (instance of %s) of the referring class, "
-          "%s, and the class loader (instance of %s) for the field's resolved "
-          "type, %s, have different Class objects for that type";
-        char* field_name = field->as_C_string();
-        const char* loader1 = SystemDictionary::loader_name(ref_loader());
-        char* sel = InstanceKlass::cast(sel_klass())->name()->as_C_string();
-        const char* loader2 = SystemDictionary::loader_name(sel_loader());
-        char* failed_type_name = failed_type_symbol->as_C_string();
-        size_t buflen = strlen(msg) + strlen(field_name) + strlen(loader1) +
-          strlen(sel) + strlen(loader2) + strlen(failed_type_name) + 1;
-        char* buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buflen);
-        jio_snprintf(buf, buflen, msg, field_name, loader1, sel, loader2,
-                     failed_type_name);
-        THROW_MSG(vmSymbols::java_lang_LinkageError(), buf);
-      }
-    }
+    check_field_loader_constraints(field, sig, current_klass, sel_klass, CHECK);
   }
 
   // return information. note that the klass is set to the actual klass containing the
@@ -873,32 +900,38 @@
 // recv_klass         the receiver klass
 
 
-void LinkResolver::resolve_static_call(CallInfo& result, KlassHandle& resolved_klass, Symbol* method_name,
-                                       Symbol* method_signature, KlassHandle current_klass,
-                                       bool check_access, bool initialize_class, TRAPS) {
-  methodHandle resolved_method;
-  linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
-  resolved_klass = KlassHandle(THREAD, resolved_method->method_holder());
+void LinkResolver::resolve_static_call(CallInfo& result,
+                                       const LinkInfo& link_info,
+                                       bool initialize_class, TRAPS) {
+  methodHandle resolved_method = linktime_resolve_static_method(link_info, CHECK);
 
+  // The resolved class can change as a result of this resolution.
+  KlassHandle resolved_klass = KlassHandle(THREAD, resolved_method->method_holder());
+
+  Method* save_resolved_method = resolved_method();
   // Initialize klass (this should only happen if everything is ok)
   if (initialize_class && resolved_klass->should_be_initialized()) {
     resolved_klass->initialize(CHECK);
-    linktime_resolve_static_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
+    // Use updated LinkInfo (to reresolve with resolved_klass as method_holder?)
+    LinkInfo new_info(resolved_klass, link_info.name(), link_info.signature(),
+                      link_info.current_klass(), link_info.check_access());
+    resolved_method = linktime_resolve_static_method(new_info, CHECK);
   }
 
+  assert(save_resolved_method == resolved_method(), "does this change?");
   // setup result
   result.set_static(resolved_klass, resolved_method, CHECK);
 }
 
 // throws linktime exceptions
-void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass,
-                                                  Symbol* method_name, Symbol* method_signature,
-                                                  KlassHandle current_klass, bool check_access, TRAPS) {
+methodHandle LinkResolver::linktime_resolve_static_method(const LinkInfo& link_info, TRAPS) {
 
+  KlassHandle resolved_klass = link_info.resolved_klass();
+  methodHandle resolved_method;
   if (!resolved_klass->is_interface()) {
-    resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK);
+    resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL);
   } else {
-    resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK);
+    resolved_method = resolve_interface_method(link_info, /*nostatics*/false, CHECK_NULL);
   }
   assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier");
 
@@ -909,22 +942,25 @@
     jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass(),
                                                       resolved_method->name(),
                                                       resolved_method->signature()));
-    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+    THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
+  return resolved_method;
 }
 
 
-void LinkResolver::resolve_special_call(CallInfo& result, KlassHandle resolved_klass, Symbol* method_name,
-                                        Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
-  methodHandle resolved_method;
-  linktime_resolve_special_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
-  runtime_resolve_special_method(result, resolved_method, resolved_klass, current_klass, check_access, CHECK);
+void LinkResolver::resolve_special_call(CallInfo& result,
+                                        const LinkInfo& link_info,
+                                        TRAPS) {
+  methodHandle resolved_method = linktime_resolve_special_method(link_info, CHECK);
+  runtime_resolve_special_method(result, resolved_method,
+                                 link_info.resolved_klass(),
+                                 link_info.current_klass(),
+                                 link_info.check_access(), CHECK);
 }
 
 // throws linktime exceptions
-void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass,
-                                                   Symbol* method_name, Symbol* method_signature,
-                                                   KlassHandle current_klass, bool check_access, TRAPS) {
+methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_info,
+                                                           TRAPS) {
 
   // Invokespecial is called for multiple special reasons:
   // <init>
@@ -932,11 +968,13 @@
   // superclass.method, which can also resolve to a default method
   // and the selected method is recalculated relative to the direct superclass
   // superinterface.method, which explicitly does not check shadowing
+  KlassHandle resolved_klass = link_info.resolved_klass();
+  methodHandle resolved_method;
 
   if (!resolved_klass->is_interface()) {
-    resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK);
+    resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL);
   } else {
-    resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK);
+    resolved_method = resolve_interface_method(link_info, /*nostatics*/true, CHECK_NULL);
   }
 
   // check if method name is <init>, that it is found in same klass as static type
@@ -951,10 +989,11 @@
       resolved_method->name()->as_C_string(),
       resolved_method->signature()->as_C_string()
     );
-    return;
+    return NULL;
   }
 
   // check if invokespecial's interface method reference is in an indirect superinterface
+  KlassHandle current_klass = link_info.current_klass();
   if (!current_klass.is_null() && resolved_klass->is_interface()) {
     Klass *klass_to_check = !InstanceKlass::cast(current_klass())->is_anonymous() ?
                                   current_klass() :
@@ -973,7 +1012,7 @@
                                                          resolved_method->name(),
                                                          resolved_method->signature()),
                    current_klass->external_name());
-      THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+      THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
     }
   }
 
@@ -984,35 +1023,26 @@
     jio_snprintf(buf, sizeof(buf),
                  "Expecting non-static method %s",
                  Method::name_and_sig_as_C_string(resolved_klass(),
-                                                         resolved_method->name(),
-                                                         resolved_method->signature()));
-    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+                                                  resolved_method->name(),
+                                                  resolved_method->signature()));
+    THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
 
   if (TraceItables && Verbose) {
-    ResourceMark rm(THREAD);
-    tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
-                (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
-                (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
-                Method::name_and_sig_as_C_string(resolved_klass(),
-                                                 resolved_method->name(),
-                                                 resolved_method->signature()),
-                resolved_method->method_holder()->internal_name()
-               );
-    resolved_method->access_flags().print_on(tty);
-    if (resolved_method->is_default_method()) {
-      tty->print("default ");
-    }
-    if (resolved_method->is_overpass()) {
-      tty->print("overpass");
-    }
+    trace_method_resolution("invokespecial resolved method: caller-class:",
+                            current_klass, resolved_klass, resolved_method);
     tty->cr();
   }
+
+  return resolved_method;
 }
 
 // throws runtime exceptions
-void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass,
-                                                  KlassHandle current_klass, bool check_access, TRAPS) {
+void LinkResolver::runtime_resolve_special_method(CallInfo& result,
+                                                  const methodHandle& resolved_method,
+                                                  KlassHandle resolved_klass,
+                                                  KlassHandle current_klass,
+                                                  bool check_access, TRAPS) {
 
   // resolved method is selected method unless we have an old-style lookup
   // for a superclass method
@@ -1037,7 +1067,7 @@
         resolved_method->name() != vmSymbols::object_initializer_name()) {
       // Lookup super method
       KlassHandle super_klass(THREAD, current_klass->super());
-      lookup_instance_method_in_klasses(sel_method, super_klass,
+      sel_method = lookup_instance_method_in_klasses(super_klass,
                            resolved_method->name(),
                            resolved_method->signature(), CHECK);
       // check if found
@@ -1066,26 +1096,13 @@
     ResourceMark rm(THREAD);
     THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
               Method::name_and_sig_as_C_string(resolved_klass(),
-                                                      sel_method->name(),
-                                                      sel_method->signature()));
+                                               sel_method->name(),
+                                               sel_method->signature()));
   }
 
   if (TraceItables && Verbose) {
-    ResourceMark rm(THREAD);
-    tty->print("invokespecial selected method: resolved-class:%s, method:%s, method_holder:%s, access_flags: ",
-                 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
-                 Method::name_and_sig_as_C_string(resolved_klass(),
-                                                  sel_method->name(),
-                                                  sel_method->signature()),
-                 sel_method->method_holder()->internal_name()
-                );
-    sel_method->access_flags().print_on(tty);
-    if (sel_method->is_default_method()) {
-      tty->print("default ");
-    }
-    if (sel_method->is_overpass()) {
-      tty->print("overpass");
-    }
+    trace_method_resolution("invokespecial selected method: resolved-class:",
+                            resolved_klass, resolved_klass, sel_method);
     tty->cr();
   }
 
@@ -1093,25 +1110,29 @@
   result.set_static(resolved_klass, sel_method, CHECK);
 }
 
-void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass,
-                                        Symbol* method_name, Symbol* method_signature, KlassHandle current_klass,
-                                        bool check_access, bool check_null_and_abstract, TRAPS) {
-  methodHandle resolved_method;
-  linktime_resolve_virtual_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
-  runtime_resolve_virtual_method(result, resolved_method, resolved_klass, recv, receiver_klass, check_null_and_abstract, CHECK);
+void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass,
+                                        const LinkInfo& link_info,
+                                        bool check_null_and_abstract, TRAPS) {
+  methodHandle resolved_method = linktime_resolve_virtual_method(link_info, CHECK);
+  runtime_resolve_virtual_method(result, resolved_method,
+                                 link_info.resolved_klass(),
+                                 recv, receiver_klass,
+                                 check_null_and_abstract, CHECK);
 }
 
 // throws linktime exceptions
-void LinkResolver::linktime_resolve_virtual_method(methodHandle &resolved_method, KlassHandle resolved_klass,
-                                                   Symbol* method_name, Symbol* method_signature,
-                                                   KlassHandle current_klass, bool check_access, TRAPS) {
+methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_info,
+                                                           TRAPS) {
   // normal method resolution
-  resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK);
+  methodHandle resolved_method = resolve_method(link_info, /*require_methodref*/true, CHECK_NULL);
 
   assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier");
   assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");
 
   // check if private interface method
+  KlassHandle resolved_klass = link_info.resolved_klass();
+  KlassHandle current_klass = link_info.current_klass();
+
   if (resolved_klass->is_interface() && resolved_method->is_private()) {
     ResourceMark rm(THREAD);
     char buf[200];
@@ -1120,7 +1141,7 @@
                                                   resolved_method->name(),
                                                   resolved_method->signature()),
                    (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()));
-    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+    THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
 
   // check if not static
@@ -1130,33 +1151,21 @@
     jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(),
                                                                                                              resolved_method->name(),
                                                                                                              resolved_method->signature()));
-    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+    THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
   }
 
   if (PrintVtables && Verbose) {
-    ResourceMark rm(THREAD);
-    tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
-                   (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()),
-                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
-                   Method::name_and_sig_as_C_string(resolved_klass(),
-                                                    resolved_method->name(),
-                                                    resolved_method->signature()),
-                   resolved_method->method_holder()->internal_name()
-                  );
-    resolved_method->access_flags().print_on(tty);
-    if (resolved_method->is_default_method()) {
-      tty->print("default ");
-    }
-    if (resolved_method->is_overpass()) {
-      tty->print("overpass");
-    }
+    trace_method_resolution("invokevirtual resolved method: caller-class:",
+                            current_klass, resolved_klass, resolved_method);
     tty->cr();
   }
+
+  return resolved_method;
 }
 
 // throws runtime exceptions
 void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
-                                                  methodHandle resolved_method,
+                                                  const methodHandle& resolved_method,
                                                   KlassHandle resolved_klass,
                                                   Handle recv,
                                                   KlassHandle recv_klass,
@@ -1227,50 +1236,40 @@
   }
 
   if (PrintVtables && Verbose) {
-    ResourceMark rm(THREAD);
-    tty->print("invokevirtual selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, vtable_index:%d, access_flags: ",
-                   (recv_klass.is_null() ? "<NULL>" : recv_klass->internal_name()),
-                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
-                   Method::name_and_sig_as_C_string(resolved_klass(),
-                                                    resolved_method->name(),
-                                                    resolved_method->signature()),
-                   selected_method->method_holder()->internal_name(),
-                   vtable_index
-                  );
-    selected_method->access_flags().print_on(tty);
-    if (selected_method->is_default_method()) {
-      tty->print("default ");
-    }
-    if (selected_method->is_overpass()) {
-      tty->print("overpass");
-    }
-    tty->cr();
+    trace_method_resolution("invokevirtual selected method: receiver-class:",
+                            recv_klass, resolved_klass, selected_method);
+    tty->print_cr("vtable_index:%d", vtable_index);
   }
   // setup result
   result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
 }
 
-void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass,
-                                          Symbol* method_name, Symbol* method_signature, KlassHandle current_klass,
-                                          bool check_access, bool check_null_and_abstract, TRAPS) {
-  methodHandle resolved_method;
-  linktime_resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
-  runtime_resolve_interface_method(result, resolved_method, resolved_klass, recv, recv_klass, check_null_and_abstract, CHECK);
+void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass,
+                                          const LinkInfo& link_info,
+                                          bool check_null_and_abstract, TRAPS) {
+  // throws linktime exceptions
+  methodHandle resolved_method = linktime_resolve_interface_method(link_info, CHECK);
+  runtime_resolve_interface_method(result, resolved_method,link_info.resolved_klass(),
+                                   recv, recv_klass, check_null_and_abstract, CHECK);
 }
 
-// throws linktime exceptions
-void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name,
-                                                     Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) {
+methodHandle LinkResolver::linktime_resolve_interface_method(const LinkInfo& link_info,
+                                                             TRAPS) {
   // normal interface method resolution
-  resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK);
-
+  methodHandle resolved_method = resolve_interface_method(link_info, true, CHECK_NULL);
   assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier");
   assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");
+
+  return resolved_method;
 }
 
 // throws runtime exceptions
-void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass,
-                                                    Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS) {
+void LinkResolver::runtime_resolve_interface_method(CallInfo& result,
+                                                    const methodHandle& resolved_method,
+                                                    KlassHandle resolved_klass,
+                                                    Handle recv,
+                                                    KlassHandle recv_klass,
+                                                    bool check_null_and_abstract, TRAPS) {
   // check if receiver exists
   if (check_null_and_abstract && recv.is_null()) {
     THROW(vmSymbols::java_lang_NullPointerException());
@@ -1298,12 +1297,11 @@
   }
 
   // do lookup based on receiver klass
-  methodHandle sel_method;
   // This search must match the linktime preparation search for itable initialization
   // to correctly enforce loader constraints for interface method inheritance
-  lookup_instance_method_in_klasses(sel_method, recv_klass,
-            resolved_method->name(),
-            resolved_method->signature(), CHECK);
+  methodHandle sel_method = lookup_instance_method_in_klasses(recv_klass,
+                                                  resolved_method->name(),
+                                                  resolved_method->signature(), CHECK);
   if (sel_method.is_null() && !check_null_and_abstract) {
     // In theory this is a harmless placeholder value, but
     // in practice leaving in null affects the nsk default method tests.
@@ -1314,9 +1312,9 @@
   if (sel_method.is_null()) {
     ResourceMark rm(THREAD);
     THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
-              Method::name_and_sig_as_C_string(recv_klass(),
-                                                      resolved_method->name(),
-                                                      resolved_method->signature()));
+                   Method::name_and_sig_as_C_string(recv_klass(),
+                                                    resolved_method->name(),
+                                                    resolved_method->signature()));
   }
   // check access
   // Throw Illegal Access Error if sel_method is not public.
@@ -1337,22 +1335,8 @@
   }
 
   if (TraceItables && Verbose) {
-    ResourceMark rm(THREAD);
-    tty->print("invokeinterface selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, access_flags: ",
-                   (recv_klass.is_null() ? "<NULL>" : recv_klass->internal_name()),
-                   (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
-                   Method::name_and_sig_as_C_string(resolved_klass(),
-                                                    resolved_method->name(),
-                                                    resolved_method->signature()),
-                   sel_method->method_holder()->internal_name()
-                  );
-    sel_method->access_flags().print_on(tty);
-    if (sel_method->is_default_method()) {
-      tty->print("default ");
-    }
-    if (sel_method->is_overpass()) {
-      tty->print("overpass");
-    }
+    trace_method_resolution("invokeinterface selected method: receiver-class",
+                            recv_klass, resolved_klass, sel_method);
     tty->cr();
   }
   // setup result
@@ -1368,14 +1352,9 @@
 
 
 methodHandle LinkResolver::linktime_resolve_interface_method_or_null(
-                                                 KlassHandle resolved_klass,
-                                                 Symbol* method_name,
-                                                 Symbol* method_signature,
-                                                 KlassHandle current_klass,
-                                                 bool check_access) {
+                                                 const LinkInfo& link_info) {
   EXCEPTION_MARK;
-  methodHandle method_result;
-  linktime_resolve_interface_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD);
+  methodHandle method_result = linktime_resolve_interface_method(link_info, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     return methodHandle();
@@ -1385,14 +1364,9 @@
 }
 
 methodHandle LinkResolver::linktime_resolve_virtual_method_or_null(
-                                                 KlassHandle resolved_klass,
-                                                 Symbol* method_name,
-                                                 Symbol* method_signature,
-                                                 KlassHandle current_klass,
-                                                 bool check_access) {
+                                                 const LinkInfo& link_info) {
   EXCEPTION_MARK;
-  methodHandle method_result;
-  linktime_resolve_virtual_method(method_result, resolved_klass, method_name, method_signature, current_klass, check_access, THREAD);
+  methodHandle method_result = linktime_resolve_virtual_method(link_info, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     return methodHandle();
@@ -1403,14 +1377,10 @@
 
 methodHandle LinkResolver::resolve_virtual_call_or_null(
                                                  KlassHandle receiver_klass,
-                                                 KlassHandle resolved_klass,
-                                                 Symbol* name,
-                                                 Symbol* signature,
-                                                 KlassHandle current_klass,
-                                                 bool check_access) {
+                                                 const LinkInfo& link_info) {
   EXCEPTION_MARK;
   CallInfo info;
-  resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, check_access, false, THREAD);
+  resolve_virtual_call(info, Handle(), receiver_klass, link_info, false, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     return methodHandle();
@@ -1420,14 +1390,10 @@
 
 methodHandle LinkResolver::resolve_interface_call_or_null(
                                                  KlassHandle receiver_klass,
-                                                 KlassHandle resolved_klass,
-                                                 Symbol* name,
-                                                 Symbol* signature,
-                                                 KlassHandle current_klass,
-                                                 bool check_access) {
+                                                 const LinkInfo& link_info) {
   EXCEPTION_MARK;
   CallInfo info;
-  resolve_interface_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, check_access, false, THREAD);
+  resolve_interface_call(info, Handle(), receiver_klass, link_info, false, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     return methodHandle();
@@ -1435,15 +1401,12 @@
   return info.selected_method();
 }
 
-int LinkResolver::resolve_virtual_vtable_index(
-                                               KlassHandle receiver_klass,
-                                               KlassHandle resolved_klass,
-                                               Symbol* name,
-                                               Symbol* signature,
-                                               KlassHandle current_klass) {
+int LinkResolver::resolve_virtual_vtable_index(KlassHandle receiver_klass,
+                                               const LinkInfo& link_info) {
   EXCEPTION_MARK;
   CallInfo info;
-  resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD);
+  resolve_virtual_call(info, Handle(), receiver_klass, link_info,
+                       /*check_null_or_abstract*/false, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     return Method::invalid_vtable_index;
@@ -1451,15 +1414,10 @@
   return info.vtable_index();
 }
 
-methodHandle LinkResolver::resolve_static_call_or_null(
-                                                  KlassHandle resolved_klass,
-                                                  Symbol* name,
-                                                  Symbol* signature,
-                                                  KlassHandle current_klass,
-                                                  bool check_access) {
+methodHandle LinkResolver::resolve_static_call_or_null(const LinkInfo& link_info) {
   EXCEPTION_MARK;
   CallInfo info;
-  resolve_static_call(info, resolved_klass, name, signature, current_klass, check_access, false, THREAD);
+  resolve_static_call(info, link_info, /*initialize_class*/false, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     return methodHandle();
@@ -1467,15 +1425,10 @@
   return info.selected_method();
 }
 
-methodHandle LinkResolver::resolve_special_call_or_null(
-                                                  KlassHandle resolved_klass,
-                                                  Symbol* name,
-                                                  Symbol* signature,
-                                                  KlassHandle current_klass,
-                                                  bool check_access) {
+methodHandle LinkResolver::resolve_special_call_or_null(const LinkInfo& link_info) {
   EXCEPTION_MARK;
   CallInfo info;
-  resolve_special_call(info, resolved_klass, name, signature, current_klass, check_access, THREAD);
+  resolve_special_call(info, link_info, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     CLEAR_PENDING_EXCEPTION;
     return methodHandle();
@@ -1500,35 +1453,15 @@
   return;
 }
 
-void LinkResolver::resolve_pool(KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature,
-                                KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS) {
-   // resolve klass
-  resolve_klass(resolved_klass, pool, index, CHECK);
-
-  // Get name, signature, and static klass
-  method_name      = pool->name_ref_at(index);
-  method_signature = pool->signature_ref_at(index);
-  current_klass    = KlassHandle(THREAD, pool->pool_holder());
-}
-
-
 void LinkResolver::resolve_invokestatic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
-  KlassHandle  resolved_klass;
-  Symbol* method_name = NULL;
-  Symbol* method_signature = NULL;
-  KlassHandle  current_klass;
-  resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
-  resolve_static_call(result, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+  LinkInfo link_info(pool, index, CHECK);
+  resolve_static_call(result, link_info, /*initialize_class*/true, CHECK);
 }
 
 
 void LinkResolver::resolve_invokespecial(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
-  KlassHandle  resolved_klass;
-  Symbol* method_name = NULL;
-  Symbol* method_signature = NULL;
-  KlassHandle  current_klass;
-  resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
-  resolve_special_call(result, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
+  LinkInfo link_info(pool, index, CHECK);
+  resolve_special_call(result, link_info, CHECK);
 }
 
 
@@ -1536,54 +1469,40 @@
                                           constantPoolHandle pool, int index,
                                           TRAPS) {
 
-  KlassHandle  resolved_klass;
-  Symbol* method_name = NULL;
-  Symbol* method_signature = NULL;
-  KlassHandle  current_klass;
-  resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
+  LinkInfo link_info(pool, index, CHECK);
   KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass());
-  resolve_virtual_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+  resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK);
 }
 
 
 void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS) {
-  KlassHandle  resolved_klass;
-  Symbol* method_name = NULL;
-  Symbol* method_signature = NULL;
-  KlassHandle  current_klass;
-  resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
+  LinkInfo link_info(pool, index, CHECK);
   KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass());
-  resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
+  resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK);
 }
 
 
 void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
   // This guy is reached from InterpreterRuntime::resolve_invokehandle.
-  KlassHandle  resolved_klass;
-  Symbol* method_name = NULL;
-  Symbol* method_signature = NULL;
-  KlassHandle  current_klass;
-  resolve_pool(resolved_klass, method_name,  method_signature, current_klass, pool, index, CHECK);
+  LinkInfo link_info(pool, index, CHECK);
   if (TraceMethodHandles) {
     ResourceMark rm(THREAD);
-    tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string());
+    tty->print_cr("resolve_invokehandle %s %s", link_info.name()->as_C_string(),
+                  link_info.signature()->as_C_string());
   }
-  resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK);
+  resolve_handle_call(result, link_info, CHECK);
 }
 
-void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_klass,
-                                       Symbol* method_name, Symbol* method_signature,
-                                       KlassHandle current_klass,
+void LinkResolver::resolve_handle_call(CallInfo& result,
+                                       const LinkInfo& link_info,
                                        TRAPS) {
   // JSR 292:  this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar
-  assert(resolved_klass() == SystemDictionary::MethodHandle_klass(), "");
-  assert(MethodHandles::is_signature_polymorphic_name(method_name), "");
-  methodHandle resolved_method;
+  assert(link_info.resolved_klass()() == SystemDictionary::MethodHandle_klass(), "");
+  assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), "");
   Handle       resolved_appendix;
   Handle       resolved_method_type;
-  lookup_polymorphic_method(resolved_method, resolved_klass,
-                            method_name, method_signature,
-                            current_klass, &resolved_appendix, &resolved_method_type, CHECK);
+  methodHandle resolved_method = lookup_polymorphic_method(link_info,
+                                       &resolved_appendix, &resolved_method_type, CHECK);
   result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
 }
 
@@ -1609,7 +1528,6 @@
 }
 
 void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
-  //resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
   Symbol* method_name       = pool->name_ref_at(index);
   Symbol* method_signature  = pool->signature_ref_at(index);
   KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder());
@@ -1667,19 +1585,27 @@
   wrap_invokedynamic_exception(CHECK);
 }
 
-//------------------------------------------------------------------------------------------------------------------------
 #ifndef PRODUCT
-
-void CallInfo::print() {
+void LinkResolver::trace_method_resolution(const char* prefix,
+                                           KlassHandle klass,
+                                           KlassHandle resolved_klass,
+                                           const methodHandle& method) {
   ResourceMark rm;
-  const char* kindstr = "unknown";
-  switch (_call_kind) {
-  case direct_call: kindstr = "direct"; break;
-  case vtable_call: kindstr = "vtable"; break;
-  case itable_call: kindstr = "itable"; break;
+  tty->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
+             prefix,
+             (klass.is_null() ? "<NULL>" : klass->internal_name()),
+             (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
+             Method::name_and_sig_as_C_string(resolved_klass(),
+                                              method->name(),
+                                              method->signature()),
+             method->method_holder()->internal_name()
+             );
+  method->access_flags().print_on(tty);
+  if (method->is_default_method()) {
+    tty->print("default ");
   }
-  tty->print_cr("Call %s@%d %s", kindstr, _call_index,
-                _resolved_method.is_null() ? "(none)" : _resolved_method->name_and_sig_as_C_string());
+  if (method->is_overpass()) {
+    tty->print("overpass ");
+  }
 }
-
-#endif
+#endif // PRODUCT
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp	Wed Jul 05 20:37:43 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
@@ -36,7 +36,7 @@
 // that method. If the info is invalid, the link has not been resolved
 // successfully.
 
-class CallInfo VALUE_OBJ_CLASS_SPEC {
+class CallInfo : public StackObj {
  public:
   // Ways that a method call might be selected (or not) based on receiver type.
   // Note that an invokevirtual instruction might be linked with no_dispatch,
@@ -58,11 +58,22 @@
   Handle       _resolved_appendix;      // extra argument in constant pool (if CPCE::has_appendix)
   Handle       _resolved_method_type;   // MethodType (for invokedynamic and invokehandle call sites)
 
-  void         set_static(   KlassHandle resolved_klass,                             methodHandle resolved_method                                                       , TRAPS);
-  void         set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index       , TRAPS);
-  void         set_virtual(  KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index       , TRAPS);
-  void         set_handle(                                                           methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS);
-  void         set_common(   KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, CallKind kind, int index, TRAPS);
+  void set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS);
+  void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass,
+                     const methodHandle& resolved_method,
+                     const methodHandle& selected_method,
+                     int itable_index, TRAPS);
+  void set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass,
+                   const methodHandle& resolved_method,
+                   const methodHandle& selected_method,
+                   int vtable_index, TRAPS);
+  void set_handle(const methodHandle& resolved_method,
+                  Handle resolved_appendix, Handle resolved_method_type, TRAPS);
+  void set_common(KlassHandle resolved_klass, KlassHandle selected_klass,
+                  const methodHandle& resolved_method,
+                  const methodHandle& selected_method,
+                  CallKind kind,
+                  int index, TRAPS);
 
   friend class LinkResolver;
 
@@ -113,6 +124,37 @@
   void         print()  PRODUCT_RETURN;
 };
 
+
+// Condensed information from constant pool to use to resolve the method or field.
+//   resolved_klass = specified class (i.e., static receiver class)
+//   current_klass  = sending method holder (i.e., class containing the method
+//                    containing the call being resolved)
+class LinkInfo : public StackObj {
+  Symbol*     _name;            // extracted from JVM_CONSTANT_NameAndType
+  Symbol*     _signature;
+  KlassHandle _resolved_klass;  // class that the constant pool entry points to
+  KlassHandle _current_klass;   // class that owns the constant pool
+  bool        _check_access;
+ public:
+  LinkInfo(constantPoolHandle pool, int index, TRAPS);
+  // Condensed information from other call sites within the vm.
+  LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
+           KlassHandle current_klass, bool check_access = true) :
+    _resolved_klass(resolved_klass),
+    _name(name), _signature(signature), _current_klass(current_klass),
+    _check_access(check_access) {}
+
+  // accessors
+  Symbol* name() const               { return _name; }
+  Symbol* signature() const          { return _signature; }
+  KlassHandle resolved_klass() const { return _resolved_klass; }
+  KlassHandle current_klass() const  { return _current_klass; }
+  bool check_access() const          { return _check_access; }
+  char* method_string() const;
+
+  void         print()  PRODUCT_RETURN;
+};
+
 // Link information for getfield/putfield & getstatic/putstatic bytecodes
 // is represented using a fieldDescriptor.
 
@@ -124,85 +166,136 @@
   friend class klassItable;
 
  private:
-  static void lookup_method_in_klasses          (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS);
-  static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
-  static void lookup_method_in_interfaces       (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
-  static void lookup_polymorphic_method         (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
-                                                 KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
+
+  static methodHandle lookup_method_in_klasses(const LinkInfo& link_info,
+                                               bool checkpolymorphism,
+                                               bool in_imethod_resolve, TRAPS);
+  static methodHandle lookup_method_in_interfaces(const LinkInfo& link_info, TRAPS);
+  static methodHandle lookup_polymorphic_method(const LinkInfo& link_info,
+                                                Handle *appendix_result_or_null,
+                                                Handle *method_type_result, TRAPS);
+  // Not Linktime so doesn't take LinkInfo
+  static methodHandle lookup_instance_method_in_klasses (
+                                       KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
 
-  static void resolve_klass           (KlassHandle& result, constantPoolHandle  pool, int index, TRAPS);
+  // Similar loader constraint checking functions that throw
+  // LinkageError with descriptive message.
+  static void check_method_loader_constraints(const LinkInfo& link_info,
+                                              const methodHandle& resolved_method,
+                                              const char* method_type, TRAPS);
+  static void check_field_loader_constraints(Symbol* field, Symbol* sig,
+                                             KlassHandle current_klass,
+                                             KlassHandle sel_klass, TRAPS);
 
-  static void resolve_pool  (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS);
+  static methodHandle resolve_interface_method(const LinkInfo& link_info, bool nostatics, TRAPS);
+  static methodHandle resolve_method          (const LinkInfo& link_info, bool require_methodref, TRAPS);
 
-  static void resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool nostatics, TRAPS);
-  static void resolve_method          (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool require_methodref, TRAPS);
+  static methodHandle linktime_resolve_static_method    (const LinkInfo& link_info, TRAPS);
+  static methodHandle linktime_resolve_special_method   (const LinkInfo& link_info, TRAPS);
+  static methodHandle linktime_resolve_virtual_method   (const LinkInfo& link_info, TRAPS);
+  static methodHandle linktime_resolve_interface_method (const LinkInfo& link_info, TRAPS);
 
-  static void linktime_resolve_static_method    (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
-  static void linktime_resolve_special_method   (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
-  static void linktime_resolve_virtual_method   (methodHandle &resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature,KlassHandle current_klass, bool check_access, TRAPS);
-  static void linktime_resolve_interface_method (methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
+  static void runtime_resolve_special_method    (CallInfo& result,
+                                                 const methodHandle& resolved_method,
+                                                 KlassHandle resolved_klass,
+                                                 KlassHandle current_klass,
+                                                 bool check_access, TRAPS);
+  static void runtime_resolve_virtual_method    (CallInfo& result,
+                                                 const methodHandle& resolved_method,
+                                                 KlassHandle resolved_klass,
+                                                 Handle recv,
+                                                 KlassHandle recv_klass,
+                                                 bool check_null_and_abstract, TRAPS);
+  static void runtime_resolve_interface_method  (CallInfo& result,
+                                                 const methodHandle& resolved_method,
+                                                 KlassHandle resolved_klass,
+                                                 Handle recv,
+                                                 KlassHandle recv_klass,
+                                                 bool check_null_and_abstract, TRAPS);
 
-  static void runtime_resolve_special_method    (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, KlassHandle current_klass, bool check_access, TRAPS);
-  static void runtime_resolve_virtual_method    (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
-  static void runtime_resolve_interface_method  (CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS);
+  static void check_field_accessability(KlassHandle ref_klass,
+                                        KlassHandle resolved_klass,
+                                        KlassHandle sel_klass,
+                                        const fieldDescriptor& fd, TRAPS);
+  static void check_method_accessability(KlassHandle ref_klass,
+                                         KlassHandle resolved_klass,
+                                         KlassHandle sel_klass,
+                                         const methodHandle& sel_method, TRAPS);
 
-  static void check_field_accessability   (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, fieldDescriptor& fd, TRAPS);
-  static void check_method_accessability  (KlassHandle ref_klass, KlassHandle resolved_klass, KlassHandle sel_klass, methodHandle sel_method, TRAPS);
-
+  // runtime resolving from constant pool
+  static void resolve_invokestatic   (CallInfo& result,
+                                      constantPoolHandle pool, int index, TRAPS);
+  static void resolve_invokespecial  (CallInfo& result,
+                                      constantPoolHandle pool, int index, TRAPS);
+  static void resolve_invokevirtual  (CallInfo& result, Handle recv,
+                                      constantPoolHandle pool, int index, TRAPS);
+  static void resolve_invokeinterface(CallInfo& result, Handle recv,
+                                      constantPoolHandle pool, int index, TRAPS);
+  static void resolve_invokedynamic  (CallInfo& result,
+                                      constantPoolHandle pool, int index, TRAPS);
+  static void resolve_invokehandle   (CallInfo& result,
+                                      constantPoolHandle pool, int index, TRAPS);
  public:
   // constant pool resolving
   static void check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS);
 
-  // static resolving calls (will not run any Java code); used only from Bytecode_invoke::static_target
-  static void resolve_method_statically(methodHandle& method_result, KlassHandle& klass_result,
-                                        Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS);
+  // static resolving calls (will not run any Java code);
+  // used only from Bytecode_invoke::static_target
+  static methodHandle resolve_method_statically(Bytecodes::Code code,
+                                                constantPoolHandle pool,
+                                                int index, TRAPS);
 
-  // runtime/static resolving for fields
-  static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
-  static void resolve_field(fieldDescriptor& result, KlassHandle resolved_klass, Symbol* field_name, Symbol* field_signature,
-                            KlassHandle current_klass, Bytecodes::Code access_kind, bool check_access, bool initialize_class, TRAPS);
-
-  // source of access_kind codes:
-  static Bytecodes::Code field_access_kind(bool is_static, bool is_put) {
-    return (is_static
-            ? (is_put ? Bytecodes::_putstatic : Bytecodes::_getstatic)
-            : (is_put ? Bytecodes::_putfield  : Bytecodes::_getfield ));
-  }
+  static void resolve_field_access(fieldDescriptor& result,
+                                   constantPoolHandle pool,
+                                   int index, Bytecodes::Code byte, TRAPS);
+  static void resolve_field(fieldDescriptor& result, const LinkInfo& link_info,
+                            Bytecodes::Code access_kind,
+                            bool initialize_class, TRAPS);
 
-  // runtime resolving:
-  //   resolved_klass = specified class (i.e., static receiver class)
-  //   current_klass  = sending method holder (i.e., class containing the method containing the call being resolved)
-  static void resolve_static_call   (CallInfo& result,              KlassHandle& resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool initialize_klass, TRAPS);
-  static void resolve_special_call  (CallInfo& result,              KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS);
-  static void resolve_virtual_call  (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
-  static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
-  static void resolve_handle_call   (CallInfo& result,                                      KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
-  static void resolve_dynamic_call  (CallInfo& result,                                      Handle bootstrap_specifier, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, TRAPS);
+  static void resolve_static_call   (CallInfo& result,
+                                     const LinkInfo& link_info,
+                                     bool initialize_klass, TRAPS);
+  static void resolve_special_call  (CallInfo& result,
+                                     const LinkInfo& link_info,
+                                     TRAPS);
+  static void resolve_virtual_call  (CallInfo& result, Handle recv, KlassHandle recv_klass,
+                                     const LinkInfo& link_info,
+                                     bool check_null_and_abstract, TRAPS);
+  static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass,
+                                     const LinkInfo& link_info,
+                                     bool check_null_and_abstract, TRAPS);
+  static void resolve_handle_call   (CallInfo& result,
+                                     const LinkInfo& link_info, TRAPS);
+  static void resolve_dynamic_call  (CallInfo& result, Handle bootstrap_specifier,
+                                     Symbol* method_name, Symbol* method_signature,
+                                     KlassHandle current_klass, TRAPS);
 
-  // same as above for compile-time resolution; but returns null handle instead of throwing an exception on error
-  // also, does not initialize klass (i.e., no side effects)
-  static methodHandle resolve_virtual_call_or_null  (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
-  static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
-  static methodHandle resolve_static_call_or_null   (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
-  static methodHandle resolve_special_call_or_null  (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true);
-  static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method);
+  // same as above for compile-time resolution; but returns null handle instead of throwing
+  // an exception on error also, does not initialize klass (i.e., no side effects)
+  static methodHandle resolve_virtual_call_or_null  (KlassHandle receiver_klass,
+                                                     const LinkInfo& link_info);
+  static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass,
+                                                     const LinkInfo& link_info);
+  static methodHandle resolve_static_call_or_null   (const LinkInfo& link_info);
+  static methodHandle resolve_special_call_or_null  (const LinkInfo& link_info);
+
+  static int vtable_index_of_interface_method(KlassHandle klass, const methodHandle& resolved_method);
 
   // same as above for compile-time resolution; returns vtable_index if current_klass if linked
-  static int resolve_virtual_vtable_index  (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass);
+  static int resolve_virtual_vtable_index  (KlassHandle receiver_klass,
+                                            const LinkInfo& link_info);
 
   // static resolving for compiler (does not throw exceptions, returns null handle if unsuccessful)
-  static methodHandle linktime_resolve_virtual_method_or_null  (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
-  static methodHandle linktime_resolve_interface_method_or_null(KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access);
+  static methodHandle linktime_resolve_virtual_method_or_null  (const LinkInfo& link_info);
+  static methodHandle linktime_resolve_interface_method_or_null(const LinkInfo& link_info);
 
   // runtime resolving from constant pool
-  static void resolve_invokestatic   (CallInfo& result,              constantPoolHandle pool, int index, TRAPS);
-  static void resolve_invokespecial  (CallInfo& result,              constantPoolHandle pool, int index, TRAPS);
-  static void resolve_invokevirtual  (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
-  static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
-  static void resolve_invokedynamic  (CallInfo& result,              constantPoolHandle pool, int index, TRAPS);
-  static void resolve_invokehandle   (CallInfo& result,              constantPoolHandle pool, int index, TRAPS);
-
-  static void resolve_invoke         (CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
+  static void resolve_invoke(CallInfo& result, Handle recv,
+                             constantPoolHandle pool, int index,
+                             Bytecodes::Code byte, TRAPS);
+ private:
+  static void trace_method_resolution(const char* prefix, KlassHandle klass,
+                                      KlassHandle resolved_klass,
+                                      const methodHandle& method) PRODUCT_RETURN;
 };
-
 #endif // SHARE_VM_INTERPRETER_LINKRESOLVER_HPP
--- a/hotspot/src/share/vm/memory/metaspace.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -614,8 +614,7 @@
   Metachunk* _chunks_in_use[NumberOfInUseLists];
   Metachunk* _current_chunk;
 
-  // Number of small chunks to allocate to a manager
-  // If class space manager, small chunks are unlimited
+  // Maximum number of small chunks to allocate to a SpaceManager
   static uint const _small_chunk_limit;
 
   // Sum of all space in allocated chunks
@@ -730,6 +729,8 @@
   // Block allocation and deallocation.
   // Allocates a block from the current chunk
   MetaWord* allocate(size_t word_size);
+  // Allocates a block from a small chunk
+  MetaWord* get_small_chunk_and_allocate(size_t word_size);
 
   // Helper for allocations
   MetaWord* allocate_work(size_t word_size);
@@ -2011,9 +2012,8 @@
 size_t SpaceManager::calc_chunk_size(size_t word_size) {
 
   // Decide between a small chunk and a medium chunk.  Up to
-  // _small_chunk_limit small chunks can be allocated but
-  // once a medium chunk has been allocated, no more small
-  // chunks will be allocated.
+  // _small_chunk_limit small chunks can be allocated.
+  // After that a medium chunk is preferred.
   size_t chunk_word_size;
   if (chunks_in_use(MediumIndex) == NULL &&
       sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
@@ -2081,7 +2081,7 @@
                             word_size, words_used, words_left);
   }
 
-  // Get another chunk out of the virtual space
+  // Get another chunk
   size_t grow_chunks_by_words = calc_chunk_size(word_size);
   Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
 
@@ -2412,6 +2412,43 @@
   return next;
 }
 
+/*
+ * The policy is to allocate up to _small_chunk_limit small chunks
+ * after which only medium chunks are allocated.  This is done to
+ * reduce fragmentation.  In some cases, this can result in a lot
+ * of small chunks being allocated to the point where it's not
+ * possible to expand.  If this happens, there may be no medium chunks
+ * available and OOME would be thrown.  Instead of doing that,
+ * if the allocation request size fits in a small chunk, an attempt
+ * will be made to allocate a small chunk.
+ */
+MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) {
+  if (word_size + Metachunk::overhead() > small_chunk_size()) {
+    return NULL;
+  }
+
+  MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
+  MutexLockerEx cl1(expand_lock(), Mutex::_no_safepoint_check_flag);
+
+  Metachunk* chunk = chunk_manager()->chunk_freelist_allocate(small_chunk_size());
+
+  MetaWord* mem = NULL;
+
+  if (chunk != NULL) {
+    // Add chunk to the in-use chunk list and do an allocation from it.
+    // Add to this manager's list of chunks in use.
+    add_chunk(chunk, false);
+    mem = chunk->allocate(word_size);
+
+    inc_used_metrics(word_size);
+
+    // Track metaspace memory usage statistic.
+    track_metaspace_memory_usage();
+  }
+
+  return mem;
+}
+
 MetaWord* SpaceManager::allocate(size_t word_size) {
   MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
 
@@ -3560,7 +3597,18 @@
   }
 
   if (result == NULL) {
-    report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
+    SpaceManager* sm;
+    if (is_class_space_allocation(mdtype)) {
+      sm = loader_data->metaspace_non_null()->class_vsm();
+    } else {
+      sm = loader_data->metaspace_non_null()->vsm();
+    }
+
+    result = sm->get_small_chunk_and_allocate(word_size);
+
+    if (result == NULL) {
+      report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
+    }
   }
 
   // Zero initialize.
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -622,14 +622,6 @@
     if (!this_k->is_linked()) {
       if (!this_k->is_rewritten()) {
         {
-          // Timer includes any side effects of class verification (resolution,
-          // etc), but not recursive entry into verify_code().
-          PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
-                                   ClassLoader::perf_class_verify_selftime(),
-                                   ClassLoader::perf_classes_verified(),
-                                   jt->get_thread_stat()->perf_recursion_counts_addr(),
-                                   jt->get_thread_stat()->perf_timers_addr(),
-                                   PerfClassTraceTime::CLASS_VERIFY);
           bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD);
           if (!verify_ok) {
             return false;
@@ -1830,11 +1822,10 @@
 // are dependent on the changes that were passed in and mark them for
 // deoptimization.  Returns the number of nmethods found.
 //
-int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
+int nmethodBucket::mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes) {
   assert_locked_or_safepoint(CodeCache_lock);
   int found = 0;
-  nmethodBucket* b = _dependencies;
-  while (b != NULL) {
+  for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
     nmethod* nm = b->get_nmethod();
     // since dependencies aren't removed until an nmethod becomes a zombie,
     // the dependency list may contain nmethods which aren't alive.
@@ -1842,7 +1833,6 @@
       if (TraceDependencies) {
         ResourceMark rm;
         tty->print_cr("Marked for deoptimization");
-        tty->print_cr("  context = %s", this->external_name());
         changes.print();
         nm->print();
         nm->print_dependencies();
@@ -1850,36 +1840,119 @@
       nm->mark_for_deoptimization();
       found++;
     }
-    b = b->next();
   }
   return found;
 }
 
+//
+// Add an nmethodBucket to the list of dependencies for this nmethod.
+// It's possible that an nmethod has multiple dependencies on this klass
+// so a count is kept for each bucket to guarantee that creation and
+// deletion of dependencies is consistent. Returns new head of the list.
+//
+nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+  for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+    if (nm == b->get_nmethod()) {
+      b->increment();
+      return deps;
+    }
+  }
+  return new nmethodBucket(nm, deps);
+}
+
+//
+// Decrement count of the nmethod in the dependency list and remove
+// the bucket completely when the count goes to 0.  This method must
+// find a corresponding bucket otherwise there's a bug in the
+// recording of dependencies. Returns true if the bucket is ready for reclamation.
+//
+bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+    if (nm == b->get_nmethod()) {
+      int val = b->decrement();
+      guarantee(val >= 0, err_msg("Underflow: %d", val));
+      return (val == 0);
+    }
+  }
+#ifdef ASSERT
+  tty->print_raw_cr("### can't find dependent nmethod");
+  nm->print();
+#endif // ASSERT
+  ShouldNotReachHere();
+  return false;
+}
+
+//
+// Reclaim all unused buckets. Returns new head of the list.
+//
+nmethodBucket* nmethodBucket::clean_dependent_nmethods(nmethodBucket* deps) {
+  nmethodBucket* first = deps;
+  nmethodBucket* last = NULL;
+  nmethodBucket* b = first;
+
+  while (b != NULL) {
+    assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
+    nmethodBucket* next = b->next();
+    if (b->count() == 0) {
+      if (last == NULL) {
+        first = next;
+      } else {
+        last->set_next(next);
+      }
+      delete b;
+      // last stays the same.
+    } else {
+      last = b;
+    }
+    b = next;
+  }
+  return first;
+}
+
+#ifndef PRODUCT
+void nmethodBucket::print_dependent_nmethods(nmethodBucket* deps, bool verbose) {
+  int idx = 0;
+  for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+    nmethod* nm = b->get_nmethod();
+    tty->print("[%d] count=%d { ", idx++, b->count());
+    if (!verbose) {
+      nm->print_on(tty, "nmethod");
+      tty->print_cr(" } ");
+    } else {
+      nm->print();
+      nm->print_dependencies();
+      tty->print_cr("--- } ");
+    }
+  }
+}
+
+bool nmethodBucket::is_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
+  for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
+    if (nm == b->get_nmethod()) {
+#ifdef ASSERT
+      int count = b->count();
+      assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
+#endif
+      return true;
+    }
+  }
+  return false;
+}
+#endif //PRODUCT
+
+int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
+  assert_locked_or_safepoint(CodeCache_lock);
+  return nmethodBucket::mark_dependent_nmethods(_dependencies, changes);
+}
+
 void InstanceKlass::clean_dependent_nmethods() {
   assert_locked_or_safepoint(CodeCache_lock);
 
   if (has_unloaded_dependent()) {
-    nmethodBucket* b = _dependencies;
-    nmethodBucket* last = NULL;
-    while (b != NULL) {
-      assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
-
-      nmethodBucket* next = b->next();
-
-      if (b->count() == 0) {
-        if (last == NULL) {
-          _dependencies = next;
-        } else {
-          last->set_next(next);
-        }
-        delete b;
-        // last stays the same.
-      } else {
-        last = b;
-      }
-
-      b = next;
-    }
+    _dependencies = nmethodBucket::clean_dependent_nmethods(_dependencies);
     set_has_unloaded_dependent(false);
   }
 #ifdef ASSERT
@@ -1893,90 +1966,26 @@
 #endif
 }
 
-//
-// Add an nmethodBucket to the list of dependencies for this nmethod.
-// It's possible that an nmethod has multiple dependencies on this klass
-// so a count is kept for each bucket to guarantee that creation and
-// deletion of dependencies is consistent.
-//
 void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
   assert_locked_or_safepoint(CodeCache_lock);
-  nmethodBucket* b = _dependencies;
-  nmethodBucket* last = NULL;
-  while (b != NULL) {
-    if (nm == b->get_nmethod()) {
-      b->increment();
-      return;
-    }
-    b = b->next();
-  }
-  _dependencies = new nmethodBucket(nm, _dependencies);
+  _dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm);
 }
 
-
-//
-// Decrement count of the nmethod in the dependency list and remove
-// the bucket competely when the count goes to 0.  This method must
-// find a corresponding bucket otherwise there's a bug in the
-// recording of dependecies.
-//
 void InstanceKlass::remove_dependent_nmethod(nmethod* nm) {
   assert_locked_or_safepoint(CodeCache_lock);
-  nmethodBucket* b = _dependencies;
-  nmethodBucket* last = NULL;
-  while (b != NULL) {
-    if (nm == b->get_nmethod()) {
-      int val = b->decrement();
-      guarantee(val >= 0, err_msg("Underflow: %d", val));
-      if (val == 0) {
-        set_has_unloaded_dependent(true);
-      }
-      return;
-    }
-    last = b;
-    b = b->next();
+
+  if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) {
+    set_has_unloaded_dependent(true);
   }
-#ifdef ASSERT
-  tty->print_cr("### %s can't find dependent nmethod:", this->external_name());
-  nm->print();
-#endif // ASSERT
-  ShouldNotReachHere();
 }
 
-
 #ifndef PRODUCT
 void InstanceKlass::print_dependent_nmethods(bool verbose) {
-  nmethodBucket* b = _dependencies;
-  int idx = 0;
-  while (b != NULL) {
-    nmethod* nm = b->get_nmethod();
-    tty->print("[%d] count=%d { ", idx++, b->count());
-    if (!verbose) {
-      nm->print_on(tty, "nmethod");
-      tty->print_cr(" } ");
-    } else {
-      nm->print();
-      nm->print_dependencies();
-      tty->print_cr("--- } ");
-    }
-    b = b->next();
-  }
+  nmethodBucket::print_dependent_nmethods(_dependencies, verbose);
 }
 
-
 bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
-  nmethodBucket* b = _dependencies;
-  while (b != NULL) {
-    if (nm == b->get_nmethod()) {
-#ifdef ASSERT
-      int count = b->count();
-      assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
-#endif
-      return true;
-    }
-    b = b->next();
-  }
-  return false;
+  return nmethodBucket::is_dependent_nmethod(_dependencies, nm);
 }
 #endif //PRODUCT
 
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1290,6 +1290,15 @@
   nmethodBucket* next()                   { return _next; }
   void set_next(nmethodBucket* b)         { _next = b; }
   nmethod* get_nmethod()                  { return _nmethod; }
+
+  static int mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes);
+  static nmethodBucket* add_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
+  static bool remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
+  static nmethodBucket* clean_dependent_nmethods(nmethodBucket* deps);
+#ifndef PRODUCT
+  static void print_dependent_nmethods(nmethodBucket* deps, bool verbose);
+  static bool is_dependent_nmethod(nmethodBucket* deps, nmethod* nm);
+#endif //PRODUCT
 };
 
 // An iterator that's used to access the inner classes indices in the
--- a/hotspot/src/share/vm/oops/klassVtable.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1136,7 +1136,7 @@
     if (m->has_itable_index()) {
       // This search must match the runtime resolution, i.e. selection search for invokeinterface
       // to correctly enforce loader constraints for interface method inheritance
-      LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK);
+      target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(), CHECK);
     }
     if (target == NULL || !target->is_public() || target->is_abstract()) {
       // Entry does not resolve. Leave it empty for AbstractMethodError.
--- a/hotspot/src/share/vm/opto/arraycopynode.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/arraycopynode.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -599,10 +599,14 @@
 }
 
 bool ArrayCopyNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
-  const TypeOopPtr* dest_t = phase->type(in(ArrayCopyNode::Dest))->is_oopptr();
+  Node* dest = in(ArrayCopyNode::Dest);
+  if (dest->is_top()) {
+    return false;
+  }
+  const TypeOopPtr* dest_t = phase->type(dest)->is_oopptr();
   assert(!dest_t->is_known_instance() || _dest_type->is_known_instance(), "result of EA not recorded");
-  const TypeOopPtr* src_t = phase->type(in(ArrayCopyNode::Src))->is_oopptr();
-  assert(!src_t->is_known_instance() || _src_type->is_known_instance(), "result of EA not recorded");
+  assert(in(ArrayCopyNode::Src)->is_top() || !phase->type(in(ArrayCopyNode::Src))->is_oopptr()->is_known_instance() ||
+         _src_type->is_known_instance(), "result of EA not recorded");
 
   if (_dest_type != TypeOopPtr::BOTTOM || t_oop->is_known_instance()) {
     assert(_dest_type == TypeOopPtr::BOTTOM || _dest_type->is_known_instance(), "result of EA is known instance");
--- a/hotspot/src/share/vm/opto/callnode.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1946,7 +1946,7 @@
         }
       }
     }
-    if (may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) {
+    if (!dest->is_top() && may_modify_arraycopy_helper(phase->type(dest)->is_oopptr(), t_oop, phase)) {
       return true;
     }
     return false;
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1457,18 +1457,18 @@
 // factory methods in "int adr_idx"
 Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
                           int adr_idx,
-                          MemNode::MemOrd mo, bool require_atomic_access) {
+                          MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency, bool require_atomic_access) {
   assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
   const TypePtr* adr_type = NULL; // debug-mode-only argument
   debug_only(adr_type = C->get_adr_type(adr_idx));
   Node* mem = memory(adr_idx);
   Node* ld;
   if (require_atomic_access && bt == T_LONG) {
-    ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo);
+    ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
   } else if (require_atomic_access && bt == T_DOUBLE) {
-    ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo);
+    ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo, control_dependency);
   } else {
-    ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo);
+    ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency);
   }
   ld = _gvn.transform(ld);
   if ((bt == T_OBJECT) && C->do_escape_analysis() || C->eliminate_boxing()) {
--- a/hotspot/src/share/vm/opto/graphKit.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -512,21 +512,24 @@
   // adapted the `do_put_xxx' and `do_get_xxx' procedures for the case
   // of volatile fields.
   Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
-                  MemNode::MemOrd mo, bool require_atomic_access = false) {
+                  MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
+                  bool require_atomic_access = false) {
     // This version computes alias_index from bottom_type
     return make_load(ctl, adr, t, bt, adr->bottom_type()->is_ptr(),
-                     mo, require_atomic_access);
+                     mo, control_dependency, require_atomic_access);
   }
   Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, const TypePtr* adr_type,
-                  MemNode::MemOrd mo, bool require_atomic_access = false) {
+                  MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
+                  bool require_atomic_access = false) {
     // This version computes alias_index from an address type
     assert(adr_type != NULL, "use other make_load factory");
     return make_load(ctl, adr, t, bt, C->get_alias_index(adr_type),
-                     mo, require_atomic_access);
+                     mo, control_dependency, require_atomic_access);
   }
   // This is the base version which is given an alias index.
   Node* make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, int adr_idx,
-                  MemNode::MemOrd mo, bool require_atomic_access = false);
+                  MemNode::MemOrd mo, LoadNode::ControlDependency control_dependency = LoadNode::DependsOnlyOnTest,
+                  bool require_atomic_access = false);
 
   // Create & transform a StoreNode and store the effect into the
   // parser's memory state.
--- a/hotspot/src/share/vm/opto/library_call.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -2631,7 +2631,9 @@
 
   if (!is_store) {
     MemNode::MemOrd mo = is_volatile ? MemNode::acquire : MemNode::unordered;
-    Node* p = make_load(control(), adr, value_type, type, adr_type, mo, is_volatile);
+    // To be valid, unsafe loads may depend on other conditions than
+    // the one that guards them: pin the Load node
+    Node* p = make_load(control(), adr, value_type, type, adr_type, mo, LoadNode::Pinned, is_volatile);
     // load value
     switch (type) {
     case T_BOOLEAN:
@@ -5488,7 +5490,7 @@
   }
   // Build the load.
   MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
-  Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, is_vol);
+  Node* loadedField = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, is_vol);
   // If reference is volatile, prevent following memory ops from
   // floating up past the volatile read.  Also prevents commoning
   // another volatile read.
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -437,7 +437,13 @@
           }
         }
         if (all_inputs_invariant) {
-          _invariant.set(n->_idx); // I am a invariant too
+          // If n's control is a predicate that was moved out of the
+          // loop, it was marked invariant but n is only invariant if
+          // it depends only on that test. Otherwise, unless that test
+          // is out of the loop, it's not invariant.
+          if (n->is_CFG() || n->depends_only_on_test() || n->in(0) == NULL || !_phase->is_member(_lpt, n->in(0))) {
+            _invariant.set(n->_idx); // I am a invariant too
+          }
         }
       } else { // process next input
         _stack.set_index(idx + 1);
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1582,13 +1582,36 @@
           if (opc != ReductionNode::opcode(opc, def_node->bottom_type()->basic_type())) {
             if (!def_node->is_reduction()) { // Not marked yet
               // To be a reduction, the arithmetic node must have the phi as input and provide a def to it
+              bool ok = false;
               for (unsigned j = 1; j < def_node->req(); j++) {
                 Node* in = def_node->in(j);
                 if (in == phi) {
-                  def_node->add_flag(Node::Flag_is_reduction);
+                  ok = true;
                   break;
                 }
               }
+
+              // do nothing if we did not match the initial criteria
+              if (ok == false) {
+                continue;
+              }
+
+              // The result of the reduction must not be used in the loop
+              for (DUIterator_Fast imax, i = def_node->fast_outs(imax); i < imax && ok; i++) {
+                Node* u = def_node->fast_out(i);
+                if (has_ctrl(u) && !loop->is_member(get_loop(get_ctrl(u)))) {
+                  continue;
+                }
+                if (u == phi) {
+                  continue;
+                }
+                ok = false;
+              }
+
+              // iff the uses conform
+              if (ok) {
+                def_node->add_flag(Node::Flag_is_reduction);
+              }
             }
           }
         }
--- a/hotspot/src/share/vm/opto/loopopts.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/loopopts.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -718,7 +718,7 @@
   }
 
   // Use same limit as split_if_with_blocks_post
-  if( C->unique() > 35000 ) return n; // Method too big
+  if( C->live_nodes() > 35000 ) return n; // Method too big
 
   // Split 'n' through the merge point if it is profitable
   Node *phi = split_thru_phi( n, n_blk, policy );
@@ -802,7 +802,7 @@
   // Cloning Cmp through Phi's involves the split-if transform.
   // FastLock is not used by an If
   if( n->is_Cmp() && !n->is_FastLock() ) {
-    if( C->unique() > 35000 ) return; // Method too big
+    if( C->live_nodes() > 35000 ) return; // Method too big
 
     // Do not do 'split-if' if irreducible loops are present.
     if( _has_irreducible_loops )
--- a/hotspot/src/share/vm/opto/matcher.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/matcher.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -844,7 +844,7 @@
   MachNode *spillCP = match_tree(new LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
 #endif
   MachNode *spillI  = match_tree(new LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered));
-  MachNode *spillL  = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered,false));
+  MachNode *spillL  = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered, LoadNode::DependsOnlyOnTest, false));
   MachNode *spillF  = match_tree(new LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered));
   MachNode *spillD  = match_tree(new LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered));
   MachNode *spillP  = match_tree(new LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered));
--- a/hotspot/src/share/vm/opto/memnode.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -784,6 +784,9 @@
     // standard dump does this in Verbose and WizardMode
     st->print(" #"); _type->dump_on(st);
   }
+  if (!_depends_only_on_test) {
+    st->print(" (does not depend only on test)");
+  }
 }
 #endif
 
@@ -800,7 +803,7 @@
 
 //----------------------------LoadNode::make-----------------------------------
 // Polymorphic factory method:
-Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo) {
+Node *LoadNode::make(PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt, MemOrd mo, ControlDependency control_dependency) {
   Compile* C = gvn.C;
 
   // sanity check the alias category against the created node type
@@ -816,39 +819,39 @@
           rt->isa_oopptr() || is_immutable_value(adr),
           "raw memory operations should have control edge");
   switch (bt) {
-  case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(),  mo);
-  case T_BYTE:    return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(),  mo);
-  case T_INT:     return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(),  mo);
-  case T_CHAR:    return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(),  mo);
-  case T_SHORT:   return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(),  mo);
-  case T_LONG:    return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo);
-  case T_FLOAT:   return new LoadFNode (ctl, mem, adr, adr_type, rt,            mo);
-  case T_DOUBLE:  return new LoadDNode (ctl, mem, adr, adr_type, rt,            mo);
-  case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(),  mo);
+  case T_BOOLEAN: return new LoadUBNode(ctl, mem, adr, adr_type, rt->is_int(),  mo, control_dependency);
+  case T_BYTE:    return new LoadBNode (ctl, mem, adr, adr_type, rt->is_int(),  mo, control_dependency);
+  case T_INT:     return new LoadINode (ctl, mem, adr, adr_type, rt->is_int(),  mo, control_dependency);
+  case T_CHAR:    return new LoadUSNode(ctl, mem, adr, adr_type, rt->is_int(),  mo, control_dependency);
+  case T_SHORT:   return new LoadSNode (ctl, mem, adr, adr_type, rt->is_int(),  mo, control_dependency);
+  case T_LONG:    return new LoadLNode (ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency);
+  case T_FLOAT:   return new LoadFNode (ctl, mem, adr, adr_type, rt,            mo, control_dependency);
+  case T_DOUBLE:  return new LoadDNode (ctl, mem, adr, adr_type, rt,            mo, control_dependency);
+  case T_ADDRESS: return new LoadPNode (ctl, mem, adr, adr_type, rt->is_ptr(),  mo, control_dependency);
   case T_OBJECT:
 #ifdef _LP64
     if (adr->bottom_type()->is_ptr_to_narrowoop()) {
-      Node* load  = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo));
+      Node* load  = gvn.transform(new LoadNNode(ctl, mem, adr, adr_type, rt->make_narrowoop(), mo, control_dependency));
       return new DecodeNNode(load, load->bottom_type()->make_ptr());
     } else
 #endif
     {
       assert(!adr->bottom_type()->is_ptr_to_narrowoop() && !adr->bottom_type()->is_ptr_to_narrowklass(), "should have got back a narrow oop");
-      return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo);
+      return new LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr(), mo, control_dependency);
     }
   }
   ShouldNotReachHere();
   return (LoadNode*)NULL;
 }
 
-LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
+LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
   bool require_atomic = true;
-  return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic);
+  return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, control_dependency, require_atomic);
 }
 
-LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) {
+LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo, ControlDependency control_dependency) {
   bool require_atomic = true;
-  return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, require_atomic);
+  return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, control_dependency, require_atomic);
 }
 
 
--- a/hotspot/src/share/vm/opto/memnode.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/memnode.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -137,7 +137,33 @@
 //------------------------------LoadNode---------------------------------------
 // Load value; requires Memory and Address
 class LoadNode : public MemNode {
+public:
+  // Some loads (from unsafe) should be pinned: they don't depend only
+  // on the dominating test.  The boolean field _depends_only_on_test
+  // below records whether that node depends only on the dominating
+  // test.
+  // Methods used to build LoadNodes pass an argument of type enum
+  // ControlDependency instead of a boolean because those methods
+  // typically have multiple boolean parameters with default values:
+  // passing the wrong boolean to one of these parameters by mistake
+  // goes easily unnoticed. Using an enum, the compiler can check that
+  // the type of a value and the type of the parameter match.
+  enum ControlDependency {
+    Pinned,
+    DependsOnlyOnTest
+  };
 private:
+  // LoadNode::hash() doesn't take the _depends_only_on_test field
+  // into account: If the graph already has a non-pinned LoadNode and
+  // we add a pinned LoadNode with the same inputs, it's safe for GVN
+  // to replace the pinned LoadNode with the non-pinned LoadNode,
+  // otherwise it wouldn't be safe to have a non pinned LoadNode with
+  // those inputs in the first place. If the graph already has a
+  // pinned LoadNode and we add a non pinned LoadNode with the same
+  // inputs, it's safe (but suboptimal) for GVN to replace the
+  // non-pinned LoadNode by the pinned LoadNode.
+  bool _depends_only_on_test;
+
   // On platforms with weak memory ordering (e.g., PPC, Ia64) we distinguish
   // loads that can be reordered, and such requiring acquire semantics to
   // adhere to the Java specification.  The required behaviour is stored in
@@ -154,8 +180,8 @@
   virtual Node* find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const;
 public:
 
-  LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo)
-    : MemNode(c,mem,adr,at), _type(rt), _mo(mo) {
+  LoadNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, MemOrd mo, ControlDependency control_dependency)
+    : MemNode(c,mem,adr,at), _type(rt), _mo(mo), _depends_only_on_test(control_dependency == DependsOnlyOnTest) {
     init_class_id(Class_Load);
   }
   inline bool is_unordered() const { return !is_acquire(); }
@@ -166,7 +192,8 @@
 
   // Polymorphic factory method:
    static Node* make(PhaseGVN& gvn, Node *c, Node *mem, Node *adr,
-                     const TypePtr* at, const Type *rt, BasicType bt, MemOrd mo);
+                     const TypePtr* at, const Type *rt, BasicType bt,
+                     MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
 
   virtual uint hash()   const;  // Check the type
 
@@ -234,16 +261,15 @@
   // which produce results (new raw memory state) inside of loops preventing all
   // manner of other optimizations).  Basically, it's ugly but so is the alternative.
   // See comment in macro.cpp, around line 125 expand_allocate_common().
-  virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; }
-
+  virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM && _depends_only_on_test; }
 };
 
 //------------------------------LoadBNode--------------------------------------
 // Load a byte (8bits signed) from memory
 class LoadBNode : public LoadNode {
 public:
-  LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
-    : LoadNode(c, mem, adr, at, ti, mo) {}
+  LoadBNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegI; }
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@@ -256,8 +282,8 @@
 // Load a unsigned byte (8bits unsigned) from memory
 class LoadUBNode : public LoadNode {
 public:
-  LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo)
-    : LoadNode(c, mem, adr, at, ti, mo) {}
+  LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegI; }
   virtual Node* Ideal(PhaseGVN *phase, bool can_reshape);
@@ -270,8 +296,8 @@
 // Load an unsigned short/char (16bits unsigned) from memory
 class LoadUSNode : public LoadNode {
 public:
-  LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
-    : LoadNode(c, mem, adr, at, ti, mo) {}
+  LoadUSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegI; }
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@@ -284,8 +310,8 @@
 // Load a short (16bits signed) from memory
 class LoadSNode : public LoadNode {
 public:
-  LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
-    : LoadNode(c, mem, adr, at, ti, mo) {}
+  LoadSNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegI; }
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
@@ -298,8 +324,8 @@
 // Load an integer from memory
 class LoadINode : public LoadNode {
 public:
-  LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo)
-    : LoadNode(c, mem, adr, at, ti, mo) {}
+  LoadINode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeInt *ti, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, ti, mo, control_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegI; }
   virtual int store_Opcode() const { return Op_StoreI; }
@@ -331,15 +357,15 @@
 
 public:
   LoadLNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const TypeLong *tl,
-            MemOrd mo, bool require_atomic_access = false)
-    : LoadNode(c, mem, adr, at, tl, mo), _require_atomic_access(require_atomic_access) {}
+            MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false)
+    : LoadNode(c, mem, adr, at, tl, mo, control_dependency), _require_atomic_access(require_atomic_access) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegL; }
   virtual int store_Opcode() const { return Op_StoreL; }
   virtual BasicType memory_type() const { return T_LONG; }
   bool require_atomic_access() const { return _require_atomic_access; }
   static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
-                                const Type* rt, MemOrd mo);
+                                const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const {
     LoadNode::dump_spec(st);
@@ -352,8 +378,8 @@
 // Load a long from unaligned memory
 class LoadL_unalignedNode : public LoadLNode {
 public:
-  LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
-    : LoadLNode(c, mem, adr, at, TypeLong::LONG, mo) {}
+  LoadL_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadLNode(c, mem, adr, at, TypeLong::LONG, mo, control_dependency) {}
   virtual int Opcode() const;
 };
 
@@ -361,8 +387,8 @@
 // Load a float (64 bits) from memory
 class LoadFNode : public LoadNode {
 public:
-  LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo)
-    : LoadNode(c, mem, adr, at, t, mo) {}
+  LoadFNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegF; }
   virtual int store_Opcode() const { return Op_StoreF; }
@@ -382,15 +408,15 @@
 
 public:
   LoadDNode(Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *t,
-            MemOrd mo, bool require_atomic_access = false)
-    : LoadNode(c, mem, adr, at, t, mo), _require_atomic_access(require_atomic_access) {}
+            MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest, bool require_atomic_access = false)
+    : LoadNode(c, mem, adr, at, t, mo, control_dependency), _require_atomic_access(require_atomic_access) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegD; }
   virtual int store_Opcode() const { return Op_StoreD; }
   virtual BasicType memory_type() const { return T_DOUBLE; }
   bool require_atomic_access() const { return _require_atomic_access; }
   static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type,
-                                const Type* rt, MemOrd mo);
+                                const Type* rt, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest);
 #ifndef PRODUCT
   virtual void dump_spec(outputStream *st) const {
     LoadNode::dump_spec(st);
@@ -403,8 +429,8 @@
 // Load a double from unaligned memory
 class LoadD_unalignedNode : public LoadDNode {
 public:
-  LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo)
-    : LoadDNode(c, mem, adr, at, Type::DOUBLE, mo) {}
+  LoadD_unalignedNode(Node *c, Node *mem, Node *adr, const TypePtr* at, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadDNode(c, mem, adr, at, Type::DOUBLE, mo, control_dependency) {}
   virtual int Opcode() const;
 };
 
@@ -412,8 +438,8 @@
 // Load a pointer from memory (either object or array)
 class LoadPNode : public LoadNode {
 public:
-  LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo)
-    : LoadNode(c, mem, adr, at, t, mo) {}
+  LoadPNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const TypePtr* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegP; }
   virtual int store_Opcode() const { return Op_StoreP; }
@@ -425,8 +451,8 @@
 // Load a narrow oop from memory (either object or array)
 class LoadNNode : public LoadNode {
 public:
-  LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo)
-    : LoadNode(c, mem, adr, at, t, mo) {}
+  LoadNNode(Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t, MemOrd mo, ControlDependency control_dependency = DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, t, mo, control_dependency) {}
   virtual int Opcode() const;
   virtual uint ideal_reg() const { return Op_RegN; }
   virtual int store_Opcode() const { return Op_StoreN; }
--- a/hotspot/src/share/vm/opto/parse3.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/parse3.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -235,7 +235,7 @@
   //
   MemNode::MemOrd mo = is_vol ? MemNode::acquire : MemNode::unordered;
   bool needs_atomic_access = is_vol || AlwaysAtomicAccesses;
-  Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, needs_atomic_access);
+  Node* ld = make_load(NULL, adr, type, bt, adr_type, mo, LoadNode::DependsOnlyOnTest, needs_atomic_access);
 
   // Adjust Java stack
   if (type2size[bt] == 1)
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1573,11 +1573,12 @@
       set_type(n, t);
       for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
         Node* m = n->fast_out(i);   // Get user
-        if( m->is_Region() ) {  // New path to Region?  Must recheck Phis too
+        if (m->is_Region()) {  // New path to Region?  Must recheck Phis too
           for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
             Node* p = m->fast_out(i2); // Propagate changes to uses
-            if( p->bottom_type() != type(p) ) // If not already bottomed out
+            if (p->bottom_type() != type(p)) { // If not already bottomed out
               worklist.push(p); // Propagate change to user
+            }
           }
         }
         // If we changed the receiver type to a call, we need to revisit
@@ -1587,12 +1588,31 @@
         if (m->is_Call()) {
           for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
             Node* p = m->fast_out(i2);  // Propagate changes to uses
-            if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1)
+            if (p->is_Proj() && p->as_Proj()->_con == TypeFunc::Control && p->outcnt() == 1) {
               worklist.push(p->unique_out());
+            }
           }
         }
-        if( m->bottom_type() != type(m) ) // If not already bottomed out
+        if (m->bottom_type() != type(m)) { // If not already bottomed out
           worklist.push(m);     // Propagate change to user
+        }
+
+        // CmpU nodes can get their type information from two nodes up in the
+        // graph (instead of from the nodes immediately above). Make sure they
+        // are added to the worklist if nodes they depend on are updated, since
+        // they could be missed and get wrong types otherwise.
+        uint m_op = m->Opcode();
+        if (m_op == Op_AddI || m_op == Op_SubI) {
+          for (DUIterator_Fast i2max, i2 = m->fast_outs(i2max); i2 < i2max; i2++) {
+            Node* p = m->fast_out(i2); // Propagate changes to uses
+            if (p->Opcode() == Op_CmpU) {
+              // Got a CmpU which might need the new type information from node n.
+              if(p->bottom_type() != type(p)) { // If not already bottomed out
+                worklist.push(p); // Propagate change to user
+              }
+            }
+          }
+        }
       }
     }
   }
--- a/hotspot/src/share/vm/opto/superword.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1631,7 +1631,7 @@
         }
         Node* adr = low_adr->in(MemNode::Address);
         const TypePtr* atyp = n->adr_type();
-        vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n));
+        vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n), control_dependency(p));
         vlen_in_bytes = vn->as_LoadVector()->memory_size();
       } else if (n->is_Store()) {
         // Promote value to be stored to vector
@@ -2280,6 +2280,19 @@
   return n;
 }
 
+LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) {
+  LoadNode::ControlDependency dep = LoadNode::DependsOnlyOnTest;
+  for (uint i = 0; i < p->size(); i++) {
+    Node* n = p->at(i);
+    assert(n->is_Load(), "only meaningful for loads");
+    if (!n->depends_only_on_test()) {
+      dep = LoadNode::Pinned;
+    }
+  }
+  return dep;
+}
+
+
 //----------------------------align_initial_loop_index---------------------------
 // Adjust pre-loop limit so that in main loop, a load/store reference
 // to align_to_ref will be a position zero in the vector.
--- a/hotspot/src/share/vm/opto/superword.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/superword.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -428,6 +428,7 @@
   Node* executed_first(Node_List* p);
   // Return the node executed last in pack p.
   Node* executed_last(Node_List* p);
+  static LoadNode::ControlDependency control_dependency(Node_List* p);
   // Alignment within a vector memory reference
   int memory_alignment(MemNode* s, int iv_adjust);
   // (Start, end] half-open range defining which operands are vector
--- a/hotspot/src/share/vm/opto/vectornode.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/vectornode.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -406,9 +406,11 @@
 
 // Return the vector version of a scalar load node.
 LoadVectorNode* LoadVectorNode::make(int opc, Node* ctl, Node* mem,
-                                     Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) {
+                                     Node* adr, const TypePtr* atyp,
+                                     uint vlen, BasicType bt,
+                                     ControlDependency control_dependency) {
   const TypeVect* vt = TypeVect::make(bt, vlen);
-  return new LoadVectorNode(ctl, mem, adr, atyp, vt);
+  return new LoadVectorNode(ctl, mem, adr, atyp, vt, control_dependency);
 }
 
 // Return the vector version of a scalar store node.
--- a/hotspot/src/share/vm/opto/vectornode.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/opto/vectornode.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -454,8 +454,8 @@
 // Load Vector from memory
 class LoadVectorNode : public LoadNode {
  public:
-  LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt)
-    : LoadNode(c, mem, adr, at, vt, MemNode::unordered) {
+  LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, ControlDependency control_dependency = LoadNode::DependsOnlyOnTest)
+    : LoadNode(c, mem, adr, at, vt, MemNode::unordered, control_dependency) {
     init_class_id(Class_LoadVector);
   }
 
@@ -471,7 +471,9 @@
   virtual int store_Opcode() const { return Op_StoreVector; }
 
   static LoadVectorNode* make(int opc, Node* ctl, Node* mem,
-                              Node* adr, const TypePtr* atyp, uint vlen, BasicType bt);
+                              Node* adr, const TypePtr* atyp,
+                              uint vlen, BasicType bt,
+                              ControlDependency control_dependency = LoadNode::DependsOnlyOnTest);
 };
 
 //------------------------------StoreVectorNode--------------------------------
--- a/hotspot/src/share/vm/prims/jni.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -1126,39 +1126,32 @@
     Method* m = Method::resolve_jmethod_id(method_id);
     number_of_parameters = m->size_of_parameters();
     Klass* holder = m->method_holder();
-    if (!(holder)->is_interface()) {
+    if (call_type != JNI_VIRTUAL) {
+        selected_method = m;
+    } else if (!m->has_itable_index()) {
       // non-interface call -- for that little speed boost, don't handlize
       debug_only(No_Safepoint_Verifier nosafepoint;)
-      if (call_type == JNI_VIRTUAL) {
-        // jni_GetMethodID makes sure class is linked and initialized
-        // so m should have a valid vtable index.
-        assert(!m->has_itable_index(), "");
-        int vtbl_index = m->vtable_index();
-        if (vtbl_index != Method::nonvirtual_vtable_index) {
-          Klass* k = h_recv->klass();
-          // k might be an arrayKlassOop but all vtables start at
-          // the same place. The cast is to avoid virtual call and assertion.
-          InstanceKlass *ik = (InstanceKlass*)k;
-          selected_method = ik->method_at_vtable(vtbl_index);
-        } else {
-          // final method
-          selected_method = m;
-        }
+      // jni_GetMethodID makes sure class is linked and initialized
+      // so m should have a valid vtable index.
+      assert(m->valid_vtable_index(), "no valid vtable index");
+      int vtbl_index = m->vtable_index();
+      if (vtbl_index != Method::nonvirtual_vtable_index) {
+        Klass* k = h_recv->klass();
+        // k might be an arrayKlassOop but all vtables start at
+        // the same place. The cast is to avoid virtual call and assertion.
+        InstanceKlass *ik = (InstanceKlass*)k;
+        selected_method = ik->method_at_vtable(vtbl_index);
       } else {
-        // JNI_NONVIRTUAL call
+        // final method
         selected_method = m;
       }
     } else {
       // interface call
       KlassHandle h_holder(THREAD, holder);
 
-      if (call_type == JNI_VIRTUAL) {
-        int itbl_index = m->itable_index();
-        Klass* k = h_recv->klass();
-        selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
-      } else {
-        selected_method = m;
-      }
+      int itbl_index = m->itable_index();
+      Klass* k = h_recv->klass();
+      selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
     }
   }
 
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -842,7 +842,7 @@
         // optimize to limit the number of times that java_sender() is called
         javaVFrame *jvf_cursor = jvf;
         javaVFrame *jvf_prev = NULL;
-        javaVFrame *jvf_prev_prev;
+        javaVFrame *jvf_prev_prev = NULL;
         int j = 0;
         while (jvf_cursor != NULL) {
           jvf_prev_prev = jvf_prev;
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -677,24 +677,24 @@
   case IS_METHOD:
     {
       CallInfo result;
+      LinkInfo link_info(defc, name, type, caller, caller.not_null());
       {
         assert(!HAS_PENDING_EXCEPTION, "");
         if (ref_kind == JVM_REF_invokeStatic) {
           LinkResolver::resolve_static_call(result,
-                        defc, name, type, caller, caller.not_null(), false, THREAD);
+                        link_info, false, THREAD);
         } else if (ref_kind == JVM_REF_invokeInterface) {
           LinkResolver::resolve_interface_call(result, Handle(), defc,
-                        defc, name, type, caller, caller.not_null(), false, THREAD);
+                        link_info, false, THREAD);
         } else if (mh_invoke_id != vmIntrinsics::_none) {
           assert(!is_signature_polymorphic_static(mh_invoke_id), "");
-          LinkResolver::resolve_handle_call(result,
-                        defc, name, type, caller, THREAD);
+          LinkResolver::resolve_handle_call(result, link_info, THREAD);
         } else if (ref_kind == JVM_REF_invokeSpecial) {
           LinkResolver::resolve_special_call(result,
-                        defc, name, type, caller, caller.not_null(), THREAD);
+                        link_info, THREAD);
         } else if (ref_kind == JVM_REF_invokeVirtual) {
           LinkResolver::resolve_virtual_call(result, Handle(), defc,
-                        defc, name, type, caller, caller.not_null(), false, THREAD);
+                        link_info, false, THREAD);
         } else {
           assert(false, err_msg("ref_kind=%d", ref_kind));
         }
@@ -714,11 +714,11 @@
   case IS_CONSTRUCTOR:
     {
       CallInfo result;
+      LinkInfo link_info(defc, name, type, caller, caller.not_null());
       {
         assert(!HAS_PENDING_EXCEPTION, "");
         if (name == vmSymbols::object_initializer_name()) {
-          LinkResolver::resolve_special_call(result,
-                        defc, name, type, caller, caller.not_null(), THREAD);
+          LinkResolver::resolve_special_call(result, link_info, THREAD);
         } else {
           break;                // will throw after end of switch
         }
@@ -735,7 +735,8 @@
       fieldDescriptor result; // find_field initializes fd if found
       {
         assert(!HAS_PENDING_EXCEPTION, "");
-        LinkResolver::resolve_field(result, defc, name, type, caller, Bytecodes::_nop, false, false, THREAD);
+        LinkInfo link_info(defc, name, type, caller, /*check_access*/false);
+        LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD);
         if (HAS_PENDING_EXCEPTION) {
           return empty;
         }
@@ -942,22 +943,56 @@
   return rfill + overflow;
 }
 
-// Get context class for a CallSite instance: either extract existing context or use default one.
-InstanceKlass* MethodHandles::get_call_site_context(oop call_site) {
-  // In order to extract a context the following traversal is performed:
-  //   CallSite.context => Cleaner.referent => Class._klass => Klass
-  assert(java_lang_invoke_CallSite::is_instance(call_site), "");
-  oop context_oop = java_lang_invoke_CallSite::context_volatile(call_site);
-  if (oopDesc::is_null(context_oop)) {
-    return NULL; // The context hasn't been initialized yet.
+void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  oop context = java_lang_invoke_CallSite::context(call_site);
+  nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
+
+  nmethodBucket* new_deps = nmethodBucket::add_dependent_nmethod(deps, nm);
+  if (deps != new_deps) {
+    java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
+  }
+}
+
+void MethodHandles::remove_dependent_nmethod(oop call_site, nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  oop context = java_lang_invoke_CallSite::context(call_site);
+  nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
+
+  if (nmethodBucket::remove_dependent_nmethod(deps, nm)) {
+    nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
+    if (deps != new_deps) {
+      java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
+    }
   }
-  oop context_class_oop = java_lang_ref_Reference::referent(context_oop);
-  if (oopDesc::is_null(context_class_oop)) {
-    // The context reference was cleared by GC, so current dependency context
-    // isn't usable anymore. Context should be fetched from CallSite again.
-    return NULL;
+}
+
+void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) {
+  assert_lock_strong(Compile_lock);
+
+  int marked = 0;
+  CallSiteDepChange changes(call_site(), target());
+  {
+    MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+
+    oop context = java_lang_invoke_CallSite::context(call_site());
+    nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
+
+    marked = nmethodBucket::mark_dependent_nmethods(deps, changes);
+    if (marked > 0) {
+      nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
+      if (deps != new_deps) {
+        java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps);
+      }
+    }
   }
-  return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop));
+  if (marked > 0) {
+    // At least one nmethod has been marked for deoptimization
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
 }
 
 //------------------------------------------------------------------------------
@@ -1276,7 +1311,7 @@
   {
     // Walk all nmethods depending on this call site.
     MutexLocker mu(Compile_lock, thread);
-    CodeCache::flush_dependents_on(call_site, target);
+    MethodHandles::flush_dependent_nmethods(call_site, target);
     java_lang_invoke_CallSite::set_target(call_site(), target());
   }
 }
@@ -1288,30 +1323,34 @@
   {
     // Walk all nmethods depending on this call site.
     MutexLocker mu(Compile_lock, thread);
-    CodeCache::flush_dependents_on(call_site, target);
+    MethodHandles::flush_dependent_nmethods(call_site, target);
     java_lang_invoke_CallSite::set_target_volatile(call_site(), target());
   }
 }
 JVM_END
 
-JVM_ENTRY(void, MHN_invalidateDependentNMethods(JNIEnv* env, jobject igcls, jobject call_site_jh)) {
-  Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
+JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) {
+  Handle context(THREAD, JNIHandles::resolve_non_null(context_jh));
   {
     // Walk all nmethods depending on this call site.
     MutexLocker mu1(Compile_lock, thread);
 
-    CallSiteDepChange changes(call_site(), Handle());
-
-    InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
-    if (ctxk == NULL) {
-      return; // No dependencies to invalidate yet.
-    }
     int marked = 0;
     {
       MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-      marked = ctxk->mark_dependent_nmethods(changes);
+      nmethodBucket* b = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context());
+      while(b != NULL) {
+        nmethod* nm = b->get_nmethod();
+        if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) {
+          nm->mark_for_deoptimization();
+          marked++;
+        }
+        nmethodBucket* next = b->next();
+        delete b;
+        b = next;
+      }
+      java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context(), NULL); // reset context
     }
-    java_lang_invoke_CallSite::set_context_volatile(call_site(), NULL); // Reset call site to initial state
     if (marked > 0) {
       // At least one nmethod has been marked for deoptimization
       VM_Deoptimize op;
@@ -1357,6 +1396,7 @@
 #define MT    JLINV"MethodType;"
 #define MH    JLINV"MethodHandle;"
 #define MEM   JLINV"MemberName;"
+#define CTX   JLINV"MethodHandleNatives$CallSiteContext;"
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
@@ -1374,7 +1414,7 @@
   {CC"objectFieldOffset",         CC"("MEM")J",                          FN_PTR(MHN_objectFieldOffset)},
   {CC"setCallSiteTargetNormal",   CC"("CS""MH")V",                       FN_PTR(MHN_setCallSiteTargetNormal)},
   {CC"setCallSiteTargetVolatile", CC"("CS""MH")V",                       FN_PTR(MHN_setCallSiteTargetVolatile)},
-  {CC"invalidateDependentNMethods", CC"("CS")V",                         FN_PTR(MHN_invalidateDependentNMethods)},
+  {CC"clearCallSiteContext",      CC"("CTX")V",                          FN_PTR(MHN_clearCallSiteContext)},
   {CC"staticFieldOffset",         CC"("MEM")J",                          FN_PTR(MHN_staticFieldOffset)},
   {CC"staticFieldBase",           CC"("MEM")"OBJ,                        FN_PTR(MHN_staticFieldBase)},
   {CC"getMemberVMInfo",           CC"("MEM")"OBJ,                        FN_PTR(MHN_getMemberVMInfo)}
--- a/hotspot/src/share/vm/prims/methodHandles.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -69,7 +69,10 @@
   enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
 
   // CallSite support
-  static InstanceKlass* get_call_site_context(oop call_site);
+  static void add_dependent_nmethod(oop call_site, nmethod* nm);
+  static void remove_dependent_nmethod(oop call_site, nmethod* nm);
+
+  static void flush_dependent_nmethods(Handle call_site, Handle target);
 
   // Generate MethodHandles adapters.
   static bool generate_adapters();
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -64,7 +64,7 @@
   }
 #endif
 
-#ifdef SPARC
+#if defined SPARC || defined AARCH64
   if (FLAG_IS_DEFAULT(InlineSmallCode)) {
     FLAG_SET_DEFAULT(InlineSmallCode, 2500);
   }
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp	Wed Jul 05 20:37:43 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
@@ -179,9 +179,9 @@
   CallInfo callinfo;
   Handle receiver = args->receiver();
   KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass());
+  LinkInfo link_info(spec_klass, name, signature, KlassHandle(), /*check_access*/false);
   LinkResolver::resolve_virtual_call(
-          callinfo, receiver, recvrKlass, spec_klass, name, signature,
-          KlassHandle(), false, true, CHECK);
+          callinfo, receiver, recvrKlass, link_info, true, CHECK);
   methodHandle method = callinfo.selected_method();
   assert(method.not_null(), "should have thrown exception");
 
@@ -216,7 +216,8 @@
 
 void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
   CallInfo callinfo;
-  LinkResolver::resolve_special_call(callinfo, klass, name, signature, KlassHandle(), false, CHECK);
+  LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
+  LinkResolver::resolve_special_call(callinfo, link_info, CHECK);
   methodHandle method = callinfo.selected_method();
   assert(method.not_null(), "should have thrown exception");
 
@@ -250,7 +251,8 @@
 
 void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
   CallInfo callinfo;
-  LinkResolver::resolve_static_call(callinfo, klass, name, signature, KlassHandle(), false, true, CHECK);
+  LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
+  LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK);
   methodHandle method = callinfo.selected_method();
   assert(method.not_null(), "should have thrown exception");
 
--- a/hotspot/src/share/vm/runtime/os.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -775,6 +775,10 @@
   pd_start_thread(thread);
 }
 
+void os::abort(bool dump_core) {
+  abort(dump_core && CreateCoredumpOnCrash, NULL, NULL);
+}
+
 //---------------------------------------------------------------------------
 // Helper functions for fatal error handler
 
--- a/hotspot/src/share/vm/runtime/reflection.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/runtime/reflection.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -831,9 +831,9 @@
   CallInfo info;
   Symbol*  signature  = method->signature();
   Symbol*  name       = method->name();
-  LinkResolver::resolve_interface_call(info, receiver, recv_klass, klass,
-                                       name, signature,
-                                       KlassHandle(), false, true,
+  LinkResolver::resolve_interface_call(info, receiver, recv_klass,
+                                       LinkInfo(klass, name, signature, KlassHandle(), false),
+                                       true,
                                        CHECK_(methodHandle()));
   return info.selected_method();
 }
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp	Wed Jul 05 20:37:43 2017 +0200
@@ -315,7 +315,7 @@
 
 void SystemGCDCmd::execute(DCmdSource source, TRAPS) {
   if (!DisableExplicitGC) {
-    Universe::heap()->collect(GCCause::_java_lang_system_gc);
+    Universe::heap()->collect(GCCause::_dcmd_gc_run);
   } else {
     output()->print_cr("Explicit GC is disabled, no GC has been performed.");
   }
--- a/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/src/share/vm/utilities/fakeRttiSupport.hpp	Wed Jul 05 20:37:43 2017 +0200
@@ -89,11 +89,11 @@
     return ((uintx)1) << validate_tag(tag);
   }
 
-  static TagType validate_tag(uintx tag) {
-    // Type of tag is not TagType to dodge useless MacOSX compiler warning.
-    assert(tag < (sizeof(uintx) * BitsPerByte),
-           err_msg("Tag " UINTX_FORMAT " is too large", tag));
-    return static_cast<TagType>(tag);
+  static TagType validate_tag(TagType tag) {
+    assert(0 <= tag, err_msg("Tag " INTX_FORMAT " is negative", (intx)tag));
+    assert(tag < BitsPerWord,
+           err_msg("Tag " UINTX_FORMAT " is too large", (uintx)tag));
+    return tag;
   }
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestDeadArrayCopyOnMemChain.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080699
+ * @summary eliminated arraycopy node still reachable through exception edges
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestDeadArrayCopyOnMemChain
+ *
+ */
+
+public class TestDeadArrayCopyOnMemChain {
+    static class A {
+        int f;
+    }
+
+    static void test_helper(Object o) {
+    }
+
+    static void test(int src_off, boolean flag) {
+        // dst is eliminated first. Eliminating dst causes src to be
+        // eliminated. When working on the safepoint at the uncommon
+        // trap in the exception handler, the eliminated ArrayCopyNode
+        // is reached through the exception edges.
+        Object[] dst = new Object[10];
+        Object[] src = new Object[10];
+
+        // src_off causes the exception handler to be run sometimes
+        try {
+            System.arraycopy(src, src_off, dst, 0, 10);
+        } catch (IndexOutOfBoundsException ioobe) {
+            // flag always false so test becomes uncommon trap. Make
+            // sure src is live at the unc.
+            if (flag) {
+                test_helper(src);
+            }
+        }
+    }
+
+    static public void main(String[] args) {
+        for (int i = 0; i < 20000; i++) {
+            test((i%2) == 0 ? 0 : -1, false);
+        }
+    }
+}
--- a/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/test/compiler/jsr292/CallSiteDepContextTest.java	Wed Jul 05 20:37:43 2017 +0200
@@ -24,12 +24,15 @@
 /**
  * @test
  * @bug 8057967
- * @ignore 8079205
- * @run main/bootclasspath -Xbatch java.lang.invoke.CallSiteDepContextTest
+ * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceClassUnloading
+ *                         -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC
+ *                         -verbose:gc java.lang.invoke.CallSiteDepContextTest
  */
 package java.lang.invoke;
 
 import java.lang.ref.*;
+import java.lang.reflect.Field;
+
 import jdk.internal.org.objectweb.asm.*;
 import sun.misc.Unsafe;
 
@@ -96,6 +99,13 @@
         }
     }
 
+    public static void testHiddenDepField() throws Exception {
+        try {
+            Field f = MethodHandleNatives.CallSiteContext.class.getDeclaredField("vmdependencies");
+            throw new AssertionError("Context.dependencies field should be hidden");
+        } catch(NoSuchFieldException e) { /* expected */ }
+    }
+
     public static void testSharedCallSite() throws Throwable {
         Class<?> cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_1"), null);
         Class<?> cls2 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_2"), null);
@@ -132,12 +142,14 @@
     static ReferenceQueue rq = new ReferenceQueue();
     static PhantomReference ref;
 
-    public static void testGC() throws Throwable {
+    public static void testGC(boolean clear, boolean precompile) throws Throwable {
+        String id = "_" + clear + "_" + precompile;
+
         mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
 
         Class<?>[] cls = new Class[] {
-                UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1"), null),
-                UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2"), null),
+                UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1" + id), null),
+                UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2" + id), null),
         };
 
         MethodHandle[] mhs = new MethodHandle[] {
@@ -151,30 +163,38 @@
         execute(1, mhs);
 
         ref = new PhantomReference<>(cls[0], rq);
-        cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3"), null);
+        cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3" + id), null);
         mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE);
 
         do {
             System.gc();
             try {
-                Reference ref1 = rq.remove(1000);
+                Reference ref1 = rq.remove(100);
                 if (ref1 == ref) {
-                    ref1.clear();
-                    System.gc(); // Ensure that the stale context is cleared
                     break;
                 }
             } catch(InterruptedException e) { /* ignore */ }
         } while (true);
 
-        execute(1, mhs);
+        if (clear) {
+            ref.clear();
+            System.gc(); // Ensure that the stale context is unloaded
+        }
+        if (precompile) {
+            execute(1, mhs);
+        }
         mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
         execute(2, mhs);
     }
 
     public static void main(String[] args) throws Throwable {
+        testHiddenDepField();
         testSharedCallSite();
         testNonBoundCallSite();
-        testGC();
+        testGC(false, false);
+        testGC(false,  true);
+        testGC( true, false);
+        testGC( true,  true);
         System.out.println("TEST PASSED");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/loopopts/superword/TestReductionWithLoopVariantUse.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080976
+ * @summary Loop variant use in reduction should prevent vectorization
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestReductionWithLoopVariantUse
+ *
+ */
+
+public class TestReductionWithLoopVariantUse {
+    static int m(int[] array) {
+        int c = 0;
+        for (int i = 0; i < 256; i++) {
+            c += array[i];
+            array[i] = c;
+        }
+        return c;
+    }
+
+    static public void main(String[] args) {
+        int[] array = new int[256];
+        int[] array2 = new int[256];
+        for (int j = 0; j < 256; j++) {
+            array2[j] = j;
+        }
+        for (int i = 0; i < 20000; i++) {
+            System.arraycopy(array2, 0, array, 0, 256);
+            int res = m(array);
+            boolean success = true;
+            int c = 0;
+            for (int j = 0; j < 256; j++) {
+                c += array2[j];
+                if (array[j] != c) {
+                    System.out.println("Failed for " + j + " : " + array[j] + " != " + c);
+                    success = false;
+                }
+            }
+            if (c != res) {
+                System.out.println("Failed for sum: " + c + " != " + res);
+            }
+            if (!success) {
+                throw new RuntimeException("Test failed");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/TestTypePropagationToCmpU.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080156 8060036
+ * @summary Test correctness of type propagation to CmpUNodes.
+ * @run main TestTypePropagationToCmpU
+ */
+public class TestTypePropagationToCmpU {
+    public static void main(String[] args) {
+        try {
+            // Trigger compilation
+            for (int i = 0; i < 100_000; ++i) {
+                test();
+            }
+        } catch (NullPointerException e) {
+            // Test should never throw a NullPointerException
+            throw new RuntimeException("Test failed");
+        }
+    }
+
+    static int global = 42;
+
+    public static void test() {
+        int a = Integer.MIN_VALUE;
+        int b = global;
+        char[] buf = { 0 };
+        for (int i = 0; i <= b; ++i) {
+            a = i - b;
+        }
+        // C2 adds a range check and an uncommon trap here to ensure that the array index
+        // is in bounds. If type information is not propagated correctly to the corresponding
+        // CmpUNode, this trap may be always taken. Because C2 also removes the unnecessary
+        // allocation of 'buf', a NullPointerException is thrown in this case.
+        char c = buf[(a * 11) / 2 - a]; // a is 0 here if global >= 0
+        buf[0] = 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/unsafe/TestUnsafeLoadControl.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8077504
+ * @summary Unsafe load can loose control dependency and cause crash
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestUnsafeLoadControl
+ *
+ */
+
+import java.lang.reflect.Field;
+import sun.misc.Unsafe;
+
+public class TestUnsafeLoadControl {
+
+    private static final Unsafe UNSAFE;
+
+    static {
+        try {
+            Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
+            unsafeField.setAccessible(true);
+            UNSAFE = (Unsafe) unsafeField.get(null);
+        } catch(Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    static int val;
+    static void test1(int[] a, boolean[] flags, boolean flag, long j) {
+        for (int i = 0; i < 10; i++) {
+            if (flags[i]) {
+                if (flag) {
+                    long address = (j << 2) + UNSAFE.ARRAY_INT_BASE_OFFSET;
+                    int v = UNSAFE.getInt(a, address);
+                    val = v;
+                }
+            }
+        }
+    }
+
+    static int test2(int[] a, boolean[] flags, boolean flag, long j) {
+        int sum = 0;
+        for (int i = 0; i < 10; i++) {
+            if (flags[i]) {
+                if (flag) {
+                    long address = (j << 2) + UNSAFE.ARRAY_INT_BASE_OFFSET;
+                    int v = UNSAFE.getInt(a, address);
+                    if (v == 0) {
+                        sum++;
+                    }
+                }
+            }
+        }
+        return sum;
+    }
+
+    static public void main(String[] args) {
+        boolean[] flags = new boolean[10];
+        for (int i = 0; i < flags.length; i++) {
+            flags[i] = true;
+        }
+        int[] array = new int[10];
+        for (int i = 0; i < 20000; i++) {
+            test1(array, flags, true, 0);
+        }
+        for (int i = 0; i < flags.length; i++) {
+            flags[i] = false;
+        }
+        test1(array, flags, true, Long.MAX_VALUE/4);
+
+        for (int i = 0; i < flags.length; i++) {
+            flags[i] = true;
+        }
+        for (int i = 0; i < 20000; i++) {
+            test2(array, flags, true, 0);
+        }
+        for (int i = 0; i < flags.length; i++) {
+            flags[i] = false;
+        }
+        test2(array, flags, true, Long.MAX_VALUE/4);
+    }
+}
--- a/hotspot/test/gc/TestSmallHeap.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/test/gc/TestSmallHeap.java	Wed Jul 05 20:37:43 2017 +0200
@@ -27,6 +27,7 @@
  * @requires vm.gc=="null"
  * @requires (vm.opt.AggressiveOpts=="null") | (vm.opt.AggressiveOpts=="false")
  * @requires vm.compMode != "Xcomp"
+ * @requires vm.opt.UseCompressedOops != false
  * @summary Verify that starting the VM with a small heap works
  * @library /testlibrary /../../test/lib
  * @modules java.management/sun.management
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ImplementationOfWithToString.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of InterfaceWithToString.
+ */
+public class ImplementationOfWithToString implements InterfaceWithToString {
+
+  /**
+   * @see InterfaceWithToString#someMethod()
+   * {@inheritDoc}
+   */
+  @Override
+  public void someMethod() {
+    // May do something here.
+  }
+
+  /**
+   * @see java.lang.Object#toString()
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString() {
+    return "toString() from " + getClass().getName();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/InterfaceWithToString.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+/**
+ * Interface with toString declared.
+ */
+public interface InterfaceWithToString {
+
+  void someMethod();
+
+  /**
+   * Same as Object.toString().
+   *
+   * @return some custom string.
+   */
+  String toString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/ToStringTest.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8072588
+ * @build InterfaceWithToString
+ * @build ImplementationOfWithToString
+ * @run main/native ToStringTest
+ */
+public final class ToStringTest {
+
+    static {
+        System.loadLibrary("ToStringTest");
+    }
+
+    native static void nTest();
+
+    public static void main(String[] args) throws Exception {
+        nTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/jni/ToStringInInterfaceTest/libToStringTest.c	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Native test for ToStringInInterfaceTest.
+ */
+
+#include "jni.h"
+
+#define checkException(env) if ((*env)->ExceptionCheck(env)) { return; }
+
+jstring callStringMethod(JNIEnv* env, jobject jobj, jmethodID id, ...)
+{
+    jstring value;
+
+    va_list ap;
+    va_start(ap, id);
+    value = (jstring)(*env)->CallObjectMethodV(env, jobj, id, ap);
+    va_end(ap);
+    return value;
+}
+
+JNIEXPORT void JNICALL Java_ToStringTest_nTest(JNIEnv* env, jclass jclazz)
+{
+    jclass classOfInterfaceWithToString;
+    jclass classOfImplementationOfWithToString;
+    jmethodID constructorOfImplementationOfWithToString;
+    jobject instanceOfImplementationOfWithToString;
+    jmethodID toStringOfInterfaceWithToString;
+    jmethodID toStringOfImplementationOfWithToString;
+    jstring jstr;
+    const char *chars;
+
+    classOfInterfaceWithToString = (*env)->FindClass(env, "InterfaceWithToString");
+    checkException(env);
+    classOfImplementationOfWithToString = (*env)->FindClass(env, "ImplementationOfWithToString");
+    checkException(env);
+
+    constructorOfImplementationOfWithToString = (*env)->GetMethodID(env, classOfImplementationOfWithToString, "<init>", "()V");
+    checkException(env);
+
+    instanceOfImplementationOfWithToString = (*env)->NewObject(env, classOfImplementationOfWithToString, constructorOfImplementationOfWithToString);
+    checkException(env);
+
+    toStringOfInterfaceWithToString = (*env)->GetMethodID(env, classOfInterfaceWithToString, "toString", "()Ljava/lang/String;");
+    checkException(env);
+
+    toStringOfImplementationOfWithToString = (*env)->GetMethodID(env, classOfImplementationOfWithToString, "toString", "()Ljava/lang/String;");
+    checkException(env);
+
+    jstr = callStringMethod(env, instanceOfImplementationOfWithToString, toStringOfImplementationOfWithToString);
+    checkException(env);
+
+    chars = (*env)->GetStringUTFChars(env, jstr, NULL);
+    (*env)->ReleaseStringUTFChars(env, jstr, chars);
+
+    jstr = callStringMethod(env, instanceOfImplementationOfWithToString, toStringOfInterfaceWithToString);
+    checkException(env);
+
+    chars = (*env)->GetStringUTFChars(env, jstr, NULL);
+    (*env)->ReleaseStringUTFChars(env, jstr, chars);
+}
--- a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java	Wed Jul 05 20:37:43 2017 +0200
@@ -59,7 +59,7 @@
         }
 
         OutputAnalyzer output = new OutputAnalyzer(gcLog, "");
-        output.shouldMatch(".*\\[Full GC \\(System(\\.gc\\(\\))?.*");
+        output.shouldContain("[Full GC (Diagnostic Command)");
     }
 
     @Test
--- a/hotspot/test/serviceability/sa/TestClassLoaderStats.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/test/serviceability/sa/TestClassLoaderStats.java	Wed Jul 05 20:37:43 2017 +0200
@@ -24,11 +24,14 @@
 import jdk.test.lib.Platform;
 import jdk.test.lib.ProcessTools;
 import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.apps.LingeredApp;
 
 /*
  * @test
+ * @library /../../test/lib/share/classes
  * @library /testlibrary
  * @build jdk.test.lib.*
+ * @build jdk.test.lib.apps.*
  * @run main TestClassLoaderStats
  */
 public class TestClassLoaderStats {
@@ -39,19 +42,27 @@
             return;
         }
 
-        ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
-                "-XX:+UsePerfData",
-                "sun.jvm.hotspot.tools.ClassLoaderStats",
-                Integer.toString(ProcessTools.getProcessId()));
-        OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
-        System.out.println(output.getOutput());
+        LingeredApp app = null;
+        try {
+            app = LingeredApp.startApp();
 
-        output.shouldHaveExitValue(0);
-        output.shouldContain("Debugger attached successfully.");
-        // The class loader stats header needs to be presented in the output:
-        output.shouldMatch("class_loader\\W+classes\\W+bytes\\W+parent_loader\\W+alive?\\W+type");
-        output.stderrShouldNotMatch("[E|e]xception");
-        output.stderrShouldNotMatch("[E|e]rror");
+            System.out.println("Attaching sun.jvm.hotspot.tools.ClassLoaderStats to " + app.getPid());
+            ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
+                    "-XX:+UsePerfData",
+                    "sun.jvm.hotspot.tools.ClassLoaderStats",
+                    Long.toString(app.getPid()));
+            OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
+            System.out.println(output.getOutput());
+
+            output.shouldHaveExitValue(0);
+            output.shouldContain("Debugger attached successfully.");
+            // The class loader stats header needs to be presented in the output:
+            output.shouldMatch("class_loader\\W+classes\\W+bytes\\W+parent_loader\\W+alive?\\W+type");
+            output.stderrShouldNotMatch("[E|e]xception");
+            output.stderrShouldNotMatch("[E|e]rror");
+        } finally {
+            app.stopApp();
+        }
     }
 
 }
--- a/hotspot/test/serviceability/sa/TestStackTrace.java	Thu Jun 11 20:18:55 2015 -0700
+++ b/hotspot/test/serviceability/sa/TestStackTrace.java	Wed Jul 05 20:37:43 2017 +0200
@@ -24,11 +24,14 @@
 import jdk.test.lib.OutputAnalyzer;
 import jdk.test.lib.Platform;
 import jdk.test.lib.ProcessTools;
+import jdk.test.lib.apps.LingeredApp;
 
 /*
  * @test
+ * @library /../../test/lib/share/classes
  * @library /testlibrary
  * @build jdk.test.lib.*
+ * @build jdk.test.lib.apps.*
  * @run main TestStackTrace
  */
 public class TestStackTrace {
@@ -39,17 +42,25 @@
             return;
         }
 
-        ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
-                "-XX:+UsePerfData",
-                "sun.jvm.hotspot.tools.StackTrace",
-                Integer.toString(ProcessTools.getProcessId()));
-        OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
-        System.out.println(output.getOutput());
+        LingeredApp app = null;
+        try {
+            app = LingeredApp.startApp();
 
-        output.shouldHaveExitValue(0);
-        output.shouldContain("Debugger attached successfully.");
-        output.stderrShouldNotMatch("[E|e]xception");
-        output.stderrShouldNotMatch("[E|e]rror");
+            System.out.println("Attaching sun.jvm.hotspot.tools.StackTrace to " + app.getPid());
+            ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
+                    "-XX:+UsePerfData",
+                    "sun.jvm.hotspot.tools.StackTrace",
+                    Long.toString(app.getPid()));
+            OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
+            System.out.println(output.getOutput());
+
+            output.shouldHaveExitValue(0);
+            output.shouldContain("Debugger attached successfully.");
+            output.stderrShouldNotMatch("[E|e]xception");
+            output.stderrShouldNotMatch("[E|e]rror");
+        } finally {
+            app.stopApp();
+        }
      }
 
 }
--- a/make/CompileJavaModules.gmk	Thu Jun 11 20:18:55 2015 -0700
+++ b/make/CompileJavaModules.gmk	Wed Jul 05 20:37:43 2017 +0200
@@ -507,6 +507,10 @@
 # space separated list.
 JDK_USER_DEFINED_FILTER := $(strip $(subst $(COMMA),$(SPACE), $(JDK_FILTER)))
 
+# Create an empty directory to set the bootclasspath to.
+EMPTY_BOOTCLASSPATH := $(SUPPORT_OUTPUTDIR)/empty-dir
+$(call MakeDir, $(EMPTY_BOOTCLASSPATH))
+
 # This macro sets up compilation of a module and declares dependencies for it.
 # Param 1 - module name
 define SetupModuleCompilation
@@ -525,7 +529,7 @@
     $1_CLASSPATH := $$($1_CLASSPATH) $$(addprefix $(JDK_OUTPUTDIR)/modules/,jdk.hotspot.agent)
   endif
   $1_CLASSPATH := $$(subst $$(SPACE),$$(PATH_SEP),$$($1_CLASSPATH))
-  $1_JAVAC_FLAGS := -bootclasspath "$$($1_CLASSPATH)" $$($1_ADD_JAVAC_FLAGS)
+  $1_JAVAC_FLAGS := -bootclasspath $(EMPTY_BOOTCLASSPATH) -classpath "$$($1_CLASSPATH)" $$($1_ADD_JAVAC_FLAGS)
 
   $$(eval $$(call SetupJavaCompilation,$1, \
       SETUP := $$(if $$($1_SETUP), $$($1_SETUP), GENERATE_JDKBYTECODE), \
--- a/make/common/JavaCompilation.gmk	Thu Jun 11 20:18:55 2015 -0700
+++ b/make/common/JavaCompilation.gmk	Wed Jul 05 20:37:43 2017 +0200
@@ -561,10 +561,6 @@
 
     $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS) $$($1_VARDEPS_FILE)
 	$(MKDIR) -p $$(@D) $$(dir $$($1_SJAVAC_PORTFILE))
-        # As a workaround for sjavac not tracking api changed from the classpath, force full
-        # recompile if an external dependency, which is something other than a source
-        # change, triggered this compilation.
-	$$(if $$(filter-out $$($1_SRCS), $$?), $(FIND) $$(@D) -name "*.class" $(FIND_DELETE))
 	$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
 	$(ECHO) Compiling $1
 	($$($1_JVM) $$($1_SJAVAC) \
--- a/make/common/NativeCompilation.gmk	Thu Jun 11 20:18:55 2015 -0700
+++ b/make/common/NativeCompilation.gmk	Wed Jul 05 20:37:43 2017 +0200
@@ -449,6 +449,16 @@
     $1_EXTRA_CXXFLAGS+=$$($1_CXXFLAGS_$(OPENJDK_TARGET_OS)_release)
   endif
 
+  # If no C++ flags are explicitly set, default to using the C flags.
+  # After that, we can set additional C++ flags that should not interfere
+  # with the mechanism for copying the C flags by default.
+  ifeq ($$($1_CXXFLAGS),)
+    $1_CXXFLAGS:=$$($1_CFLAGS)
+  endif
+  ifeq ($$(strip $$($1_EXTRA_CXXFLAGS)),)
+    $1_EXTRA_CXXFLAGS:=$$($1_EXTRA_CFLAGS)
+  endif
+
   ifeq ($$($1_DEBUG_SYMBOLS), true)
     ifeq ($(ENABLE_DEBUG_SYMBOLS), true)
       ifdef OPENJDK
@@ -466,16 +476,6 @@
     endif
   endif
 
-  # If no C++ flags are explicitly set, default to using the C flags.
-  # After that, we can set additional C++ flags that should not interfere
-  # with the mechanism for copying the C flags by default.
-  ifeq ($$($1_CXXFLAGS),)
-    $1_CXXFLAGS:=$$($1_CFLAGS)
-  endif
-  ifeq ($$(strip $$($1_EXTRA_CXXFLAGS)),)
-    $1_EXTRA_CXXFLAGS:=$$($1_EXTRA_CFLAGS)
-  endif
-
   ifneq (,$$($1_REORDER))
     $1_EXTRA_CFLAGS += $$(C_FLAG_REORDER)
     $1_EXTRA_CXXFLAGS += $$(CXX_FLAG_REORDER)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib-test/jdk/test/lib/apps/LingeredAppTest.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Unit test for LingeredApp
+ * @compile LingeredAppTest.java
+ * @compile LingeredApp.java
+ * @run main LingeredAppTest
+ */
+
+package jdk.test.lib.apps;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class LingeredAppTest {
+
+    public static void main(String[] args) {
+        try {
+            System.out.println("Starting LingeredApp with default parameters");
+
+            ArrayList<String> cmd = new ArrayList<String>();
+
+            // Propagate test.vm.options to LingeredApp, filter out possible empty options
+            String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
+            for (String s : testVmOpts) {
+                if (!s.equals("")) {
+                    cmd.add(s);
+                }
+            }
+
+            cmd.add("-XX:+PrintFlagsFinal");
+
+            LingeredApp a = LingeredApp.startApp(cmd);
+            System.out.printf("App pid: %d\n", a.getPid());
+            a.stopApp();
+
+            System.out.println("App output:");
+            int count = 0;
+            for (String line : a.getAppOutput()) {
+                count += 1;
+            }
+            System.out.println("Found " + count + " lines in VM output");
+            System.out.println("Test PASSED");
+        } catch (IOException ex) {
+            ex.printStackTrace();
+            System.out.println("Test ERROR");
+            System.exit(3);
+        }
+    }
+}
--- a/test/lib/Makefile	Thu Jun 11 20:18:55 2015 -0700
+++ b/test/lib/Makefile	Wed Jul 05 20:37:43 2017 +0200
@@ -42,7 +42,8 @@
 JAR = $(JDK_HOME)/bin/jar
 
 WB_SRC_FILES = $(shell find $(SRC_DIR)/sun/hotspot -name '*.java')
-SHARE_SRC_FILES = $(shell find $(SRC_DIR)/share/classes -name '*.java')
+# test-lib.jar will contain only hprof classes until JDK-8081381 is resolved
+SHARE_SRC_FILES = $(shell find $(SRC_DIR)/share/classes/jdk/test/lib/hprof -name '*.java')
 
 .PHONY: wb.filelist share.filelist clean cleantmp
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/apps/LingeredApp.java	Wed Jul 05 20:37:43 2017 +0200
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.lib.apps;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * This is a framework to launch an app that could be synchronized with caller
+ * to make further attach actions reliable across supported platforms
+
+ * Caller example:
+ *   SmartTestApp a = SmartTestApp.startApp(cmd);
+ *     // do something
+ *   a.stopApp();
+ *
+ *   or fine grained control
+ *
+ *   a = new SmartTestApp("MyLock.lck");
+ *   a.createLock();
+ *   a.runApp();
+ *   a.waitAppReady();
+ *     // do something
+ *   a.deleteLock();
+ *   a.waitAppTerminate();
+ *
+ *  Then you can work with app output and process object
+ *
+ *   output = a.getAppOutput();
+ *   process = a.getProcess();
+ *
+ */
+public class LingeredApp {
+
+    private static final long spinDelay = 1000;
+
+    private final String lockFileName;
+    private long lockCreationTime;
+    private Process appProcess;
+    private final ArrayList<String> storedAppOutput;
+
+    /*
+     * Drain child process output, store it into string array
+     */
+    class InputGobbler extends Thread {
+
+        InputStream is;
+        List<String> astr;
+
+        InputGobbler(InputStream is, List<String> astr) {
+            this.is = is;
+            this.astr = astr;
+        }
+
+        public void run() {
+            try {
+                InputStreamReader isr = new InputStreamReader(is);
+                BufferedReader br = new BufferedReader(isr);
+                String line = null;
+                while ((line = br.readLine()) != null) {
+                    astr.add(line);
+                }
+            } catch (IOException ex) {
+                // pass
+            }
+        }
+    }
+
+    /**
+     * Create LingeredApp object on caller side. Lock file have be a valid filename
+     * at writable location
+     *
+     * @param lockFileName - the name of lock file
+     */
+    public LingeredApp(String lockFileName) {
+        this.lockFileName = lockFileName;
+        this.storedAppOutput = new ArrayList<String>();
+    }
+
+    /**
+     *
+     * @return name of lock file
+     */
+    public String getLockFileName() {
+        return this.lockFileName;
+    }
+
+    /**
+     *
+     * @return name of testapp
+     */
+    public String getAppName() {
+        return this.getClass().getName();
+    }
+
+    /**
+     *
+     *  @return pid of java process running testapp
+     */
+    public long getPid() {
+        if (appProcess == null) {
+            throw new RuntimeException("Process is not alive");
+        }
+        return appProcess.getPid();
+    }
+
+    /**
+     *
+     * @return process object
+     */
+    public Process getProcess() {
+        return appProcess;
+    }
+
+    /**
+     *
+     * @return application output as string array. Empty array if application produced no output
+     */
+    public List<String> getAppOutput() {
+        if (appProcess.isAlive()) {
+            throw new RuntimeException("Process is still alive. Can't get its output.");
+        }
+        return storedAppOutput;
+    }
+
+    /* Make sure all part of the app use the same method to get dates,
+     as different methods could produce different results
+     */
+    private static long epoch() {
+        return new Date().getTime();
+    }
+
+    private static long lastModified(String fileName) throws IOException {
+        Path path = Paths.get(fileName);
+        BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
+        return attr.lastModifiedTime().toMillis();
+    }
+
+    private static void setLastModified(String fileName, long newTime) throws IOException {
+        Path path = Paths.get(fileName);
+        FileTime fileTime = FileTime.fromMillis(newTime);
+        Files.setLastModifiedTime(path, fileTime);
+    }
+
+    /**
+     * create lock
+     *
+     * @throws IOException
+     */
+    public void createLock() throws IOException {
+        Path path = Paths.get(lockFileName);
+        // Files.deleteIfExists(path);
+        Files.createFile(path);
+        lockCreationTime = lastModified(lockFileName);
+    }
+
+    /**
+     * Delete lock
+     *
+     * @throws IOException
+     */
+    public void deleteLock() throws IOException {
+        try {
+            Path path = Paths.get(lockFileName);
+            Files.delete(path);
+        } catch (NoSuchFileException ex) {
+            // Lock already deleted. Ignore error
+        }
+    }
+
+    public void waitAppTerminate() {
+        while (true) {
+            try {
+                appProcess.waitFor();
+                break;
+            } catch (InterruptedException ex) {
+                // pass
+            }
+        }
+    }
+
+    /**
+     * The app touches the lock file when it's started
+     * wait while it happens. Caller have to delete lock on wait error.
+     *
+     * @param timeout
+     * @throws java.io.IOException
+     */
+    public void waitAppReady(long timeout) throws IOException {
+        long here = epoch();
+        while (true) {
+            long epoch = epoch();
+            if (epoch - here > (timeout * 1000)) {
+                throw new IOException("App waiting timeout");
+            }
+
+            // Live process should touch lock file every second
+            long lm = lastModified(lockFileName);
+            if (lm > lockCreationTime) {
+                break;
+            }
+
+            // Make sure process didn't already exit
+            if (!appProcess.isAlive()) {
+                throw new IOException("App exited unexpectedly with " + appProcess.exitValue());
+            }
+
+            try {
+                Thread.sleep(spinDelay);
+            } catch (InterruptedException ex) {
+                // pass
+            }
+        }
+    }
+
+    /**
+     * Run the app
+     *
+     * @param vmArguments
+     * @throws IOException
+     */
+    public void runApp(List<String> vmArguments)
+            throws IOException {
+
+        // We should always use testjava or throw an exception,
+        // so we can't use JDKToolFinder.getJDKTool("java");
+        // that falls back to compile java on error
+        String jdkPath = System.getProperty("test.jdk");
+        if (jdkPath == null) {
+            // we are not under jtreg, try env
+            Map<String, String> env = System.getenv();
+            jdkPath = env.get("TESTJAVA");
+        }
+
+        if (jdkPath == null) {
+            throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set");
+        }
+
+        String osname = System.getProperty("os.name");
+        String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java");
+
+        List<String> cmd = new ArrayList<String>();
+        cmd.add(javapath);
+
+
+        if (vmArguments == null) {
+            // Propagate test.vm.options to LingeredApp, filter out possible empty options
+            String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
+            for (String s : testVmOpts) {
+                if (!s.equals("")) {
+                    cmd.add(s);
+                }
+            }
+        }
+        else{
+            // Lets user manage LingerApp options
+            cmd.addAll(vmArguments);
+        }
+
+        // Make sure we set correct classpath to run the app
+        cmd.add("-cp");
+        String classpath = System.getProperty("test.class.path");
+        cmd.add((classpath == null) ? "." : classpath);
+
+        cmd.add(this.getAppName());
+        cmd.add(lockFileName);
+
+        // Reporting
+        StringBuilder cmdLine = new StringBuilder();
+        for (String strCmd : cmd) {
+            cmdLine.append("'").append(strCmd).append("' ");
+        }
+
+        // A bit of verbosity
+        System.out.println("Command line: [" + cmdLine.toString() + "]");
+
+        ProcessBuilder pb = new ProcessBuilder(cmd);
+        // we don't expect any error output but make sure we are not stuck on pipe
+        // pb.redirectErrorStream(false);
+        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+        appProcess = pb.start();
+
+        // Create pipe reader for process, and read stdin and stderr to array of strings
+        InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
+        gb.start();
+    }
+
+    /**
+     *  High level interface for test writers
+     */
+    /**
+     * Factory method that creates SmartAppTest object with ready to use application
+     * lock name is autogenerated, wait timeout is hardcoded
+     * @param cmd - vm options, could be null to auto add testvm.options
+     * @return LingeredApp object
+     * @throws IOException
+     */
+    public static LingeredApp startApp(List<String> cmd) throws IOException {
+        final String lockName = UUID.randomUUID().toString() + ".lck";
+        final int waitTime = 10;
+
+        LingeredApp a = new LingeredApp(lockName);
+        a.createLock();
+        try {
+            a.runApp(cmd);
+            a.waitAppReady(waitTime);
+        } catch (Exception ex) {
+            a.deleteLock();
+            throw ex;
+        }
+
+        return a;
+    }
+
+    public static LingeredApp startApp() throws IOException {
+        return startApp(null);
+    }
+
+    /**
+     * Delete lock file that signal app to terminate, then
+     * waits until app is actually terminated.
+     * @throws IOException
+     */
+    public void stopApp() throws IOException {
+        deleteLock();
+        waitAppTerminate();
+        int exitcode = appProcess.exitValue();
+        if (exitcode != 0) {
+            throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
+        }
+    }
+
+    /**
+     * LastModified time might not work correctly in some cases it might
+     * cause later failures
+     */
+
+    public static boolean isLastModifiedWorking() {
+        boolean sane = true;
+        try {
+            long lm = lastModified(".");
+            if (lm == 0) {
+                System.err.println("SANITY Warning! The lastModifiedTime() doesn't work on this system, it returns 0");
+                sane = false;
+            }
+
+            long now = epoch();
+            if (lm > now) {
+                System.err.println("SANITY Warning! The Clock is wrong on this system lastModifiedTime() > getTime()");
+                sane = false;
+            }
+
+            setLastModified(".", epoch());
+            long lm1 = lastModified(".");
+            if (lm1 <= lm) {
+                System.err.println("SANITY Warning! The setLastModified doesn't work on this system");
+                sane = false;
+            }
+        }
+        catch(IOException e) {
+            System.err.println("SANITY Warning! IOException during sanity check " + e);
+            sane = false;
+        }
+
+        return sane;
+    }
+
+    /**
+     * This part is the application it self
+     */
+    public static void main(String args[]) {
+
+        if (args.length != 1) {
+            System.err.println("Lock file name is not specified");
+            System.exit(7);
+        }
+
+        String theLockFileName = args[0];
+
+        try {
+            Path path = Paths.get(theLockFileName);
+
+            while (Files.exists(path)) {
+                // Touch the lock to indicate our readiness
+                setLastModified(theLockFileName, epoch());
+                Thread.sleep(spinDelay);
+            }
+        } catch (NoSuchFileException ex) {
+            // Lock deleted while we are setting last modified time.
+            // Ignore error and lets the app exits
+        } catch (Exception ex) {
+            System.err.println("LingeredApp ERROR: " + ex);
+            // Leave exit_code = 1 to Java launcher
+            System.exit(3);
+        }
+
+        System.exit(0);
+    }
+}