diff -r e4a89dfa1247 -r c3c04b6e14f8 src/hotspot/share/interpreter/linkResolver.cpp --- 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,