src/hotspot/share/interpreter/linkResolver.cpp
changeset 47684 c3c04b6e14f8
parent 47216 71c04702a3d5
child 47701 be620a591379
child 47765 b7c7428eaab9
--- a/src/hotspot/share/interpreter/linkResolver.cpp	Mon Oct 23 10:45:07 2017 +0000
+++ b/src/hotspot/share/interpreter/linkResolver.cpp	Mon Oct 23 10:42:26 2017 -0400
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/defaultMethods.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/resolutionErrors.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -1696,8 +1697,22 @@
   Handle bootstrap_specifier;
   // Check if CallSite has been bound already:
   ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index);
+  int pool_index = cpce->constant_pool_index();
+
   if (cpce->is_f1_null()) {
-    int pool_index = cpce->constant_pool_index();
+    if (cpce->indy_resolution_failed()) {
+      ConstantPool::throw_resolution_error(pool,
+                                           ResolutionErrorTable::encode_cpcache_index(index),
+                                           CHECK);
+    }
+
+    // The initial step in Call Site Specifier Resolution is to resolve the symbolic
+    // reference to a method handle which will be the bootstrap method for a dynamic
+    // call site.  If resolution for the java.lang.invoke.MethodHandle for the bootstrap
+    // method fails, then a MethodHandleInError is stored at the corresponding bootstrap
+    // method's CP index for the CONSTANT_MethodHandle_info.  So, there is no need to
+    // set the indy_rf flag since any subsequent invokedynamic instruction which shares
+    // this bootstrap method will encounter the resolution of MethodHandleInError.
     oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, THREAD);
     wrap_invokedynamic_exception(CHECK);
     assert(bsm_info != NULL, "");
@@ -1722,7 +1737,31 @@
     tty->print("  BSM info: "); bootstrap_specifier->print();
   }
 
-  resolve_dynamic_call(result, bootstrap_specifier, method_name, method_signature, current_klass, CHECK);
+  resolve_dynamic_call(result, bootstrap_specifier, method_name,
+                       method_signature, current_klass, THREAD);
+  if (HAS_PENDING_EXCEPTION && PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
+    int encoded_index = ResolutionErrorTable::encode_cpcache_index(index);
+    bool recorded_res_status = cpce->save_and_throw_indy_exc(pool, pool_index,
+                                                             encoded_index,
+                                                             pool()->tag_at(pool_index),
+                                                             CHECK);
+    if (!recorded_res_status) {
+      // Another thread got here just before we did.  So, either use the method
+      // that it resolved or throw the LinkageError exception that it threw.
+      if (!cpce->is_f1_null()) {
+        methodHandle method(     THREAD, cpce->f1_as_method());
+        Handle       appendix(   THREAD, cpce->appendix_if_resolved(pool));
+        Handle       method_type(THREAD, cpce->method_type_if_resolved(pool));
+        result.set_handle(method, appendix, method_type, THREAD);
+        wrap_invokedynamic_exception(CHECK);
+      } else {
+        assert(cpce->indy_resolution_failed(), "Resolution failure flag not set");
+        ConstantPool::throw_resolution_error(pool, encoded_index, CHECK);
+      }
+      return;
+    }
+    assert(cpce->indy_resolution_failed(), "Resolution failure flag wasn't set");
+  }
 }
 
 void LinkResolver::resolve_dynamic_call(CallInfo& result,