src/hotspot/share/oops/cpCache.cpp
changeset 47684 c3c04b6e14f8
parent 47634 6a0c42c40cd1
child 47890 2219a502fd45
--- a/src/hotspot/share/oops/cpCache.cpp	Mon Oct 23 10:45:07 2017 +0000
+++ b/src/hotspot/share/oops/cpCache.cpp	Mon Oct 23 10:42:26 2017 -0400
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "classfile/resolutionErrors.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/interpreter.hpp"
@@ -110,6 +111,10 @@
   OrderAccess::release_store(&_f1, f1);
 }
 
+void ConstantPoolCacheEntry::set_indy_resolution_failed() {
+  OrderAccess::release_store(&_flags, _flags | (1 << indy_resolution_failed_shift));
+}
+
 // Note that concurrent update of both bytecodes can leave one of them
 // reset to zero.  This is harmless; the interpreter will simply re-resolve
 // the damaged entry.  More seriously, the memory synchronization is needed
@@ -318,6 +323,25 @@
     return;
   }
 
+  if (indy_resolution_failed()) {
+    // Before we got here, another thread got a LinkageError exception during
+    // resolution.  Ignore our success and throw their exception.
+    ConstantPoolCache* cpCache = cpool->cache();
+    int index = -1;
+    for (int i = 0; i < cpCache->length(); i++) {
+      if (cpCache->entry_at(i) == this) {
+        index = i;
+        break;
+      }
+    }
+    guarantee(index >= 0, "Didn't find cpCache entry!");
+    int encoded_index = ResolutionErrorTable::encode_cpcache_index(
+                          ConstantPool::encode_invokedynamic_index(index));
+    Thread* THREAD = Thread::current();
+    ConstantPool::throw_resolution_error(cpool, encoded_index, THREAD);
+    return;
+  }
+
   const methodHandle adapter = call_info.resolved_method();
   const Handle appendix      = call_info.resolved_appendix();
   const Handle method_type   = call_info.resolved_method_type();
@@ -389,6 +413,40 @@
   }
 }
 
+bool ConstantPoolCacheEntry::save_and_throw_indy_exc(
+  const constantPoolHandle& cpool, int cpool_index, int index, constantTag tag, TRAPS) {
+
+  assert(HAS_PENDING_EXCEPTION, "No exception got thrown!");
+  assert(PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass()),
+         "No LinkageError exception");
+
+  // Use the resolved_references() lock for this cpCache entry.
+  // resolved_references are created for all classes with Invokedynamic, MethodHandle
+  // or MethodType constant pool cache entries.
+  objArrayHandle resolved_references(Thread::current(), cpool->resolved_references());
+  assert(resolved_references() != NULL,
+         "a resolved_references array should have been created for this class");
+  ObjectLocker ol(resolved_references, THREAD);
+
+  // if f1 is not null or the indy_resolution_failed flag is set then another
+  // thread either succeeded in resolving the method or got a LinkageError
+  // exception, before this thread was able to record its failure.  So, clear
+  // this thread's exception and return false so caller can use the earlier
+  // thread's result.
+  if (!is_f1_null() || indy_resolution_failed()) {
+    CLEAR_PENDING_EXCEPTION;
+    return false;
+  }
+
+  Symbol* error = PENDING_EXCEPTION->klass()->name();
+  Symbol* message = java_lang_Throwable::detail_message(PENDING_EXCEPTION);
+  assert("message != NULL", "Missing detail message");
+
+  SystemDictionary::add_resolution_error(cpool, index, error, message);
+  set_indy_resolution_failed();
+  return true;
+}
+
 Method* ConstantPoolCacheEntry::method_if_resolved(const constantPoolHandle& cpool) {
   // Decode the action of set_method and set_interface_call
   Bytecodes::Code invoke_code = bytecode_1();