diff -r f5657f30bb01 -r 69cfd80f8706 src/hotspot/share/oops/constantPool.cpp --- a/src/hotspot/share/oops/constantPool.cpp Tue Apr 23 08:11:38 2019 -0700 +++ b/src/hotspot/share/oops/constantPool.cpp Tue Apr 23 14:09:54 2019 -0400 @@ -30,6 +30,7 @@ #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" +#include "interpreter/bootstrapInfo.hpp" #include "interpreter/linkResolver.hpp" #include "memory/allocation.inline.hpp" #include "memory/heapInspection.hpp" @@ -909,9 +910,8 @@ case JVM_CONSTANT_Dynamic: { - Klass* current_klass = this_cp->pool_holder(); - Symbol* constant_name = this_cp->uncached_name_ref_at(index); - Symbol* constant_type = this_cp->uncached_signature_ref_at(index); + // Resolve the Dynamically-Computed constant to invoke the BSM in order to obtain the resulting oop. + BootstrapInfo bootstrap_specifier(this_cp, index); // The initial step in resolving an unresolved symbolic reference to a // dynamically-computed constant is to resolve the symbolic reference to a @@ -921,27 +921,18 @@ // bootstrap method's CP index for the CONSTANT_MethodHandle_info. No need to // set a DynamicConstantInError here since any subsequent use of this // bootstrap method will encounter the resolution of MethodHandleInError. - oop bsm_info = this_cp->resolve_bootstrap_specifier_at(index, THREAD); - Exceptions::wrap_dynamic_exception(CHECK_NULL); - assert(bsm_info != NULL, ""); - // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_Dynamic. - Handle bootstrap_specifier = Handle(THREAD, bsm_info); - - // Resolve the Dynamically-Computed constant to invoke the BSM in order to obtain the resulting oop. - Handle value = SystemDictionary::link_dynamic_constant(current_klass, - index, - bootstrap_specifier, - constant_name, - constant_type, - THREAD); - result_oop = value(); + // Both the first, (resolution of the BSM and its static arguments), and the second tasks, + // (invocation of the BSM), of JVMS Section 5.4.3.6 occur within invoke_bootstrap_method() + // for the bootstrap_specifier created above. + SystemDictionary::invoke_bootstrap_method(bootstrap_specifier, THREAD); Exceptions::wrap_dynamic_exception(THREAD); if (HAS_PENDING_EXCEPTION) { // Resolution failure of the dynamically-computed constant, save_and_throw_exception // will check for a LinkageError and store a DynamicConstantInError. save_and_throw_exception(this_cp, index, tag, CHECK_NULL); } - BasicType type = FieldType::basic_type(constant_type); + result_oop = bootstrap_specifier.resolved_value()(); + BasicType type = FieldType::basic_type(bootstrap_specifier.signature()); if (!is_reference_type(type)) { // Make sure the primitive value is properly boxed. // This is a JDK responsibility. @@ -961,6 +952,10 @@ THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), fail); } } + + if (TraceMethodHandles) { + bootstrap_specifier.print_msg_on(tty, "resolve_constant_at_impl"); + } break; } @@ -1102,119 +1097,6 @@ return str; } - -oop ConstantPool::resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS) { - assert((this_cp->tag_at(index).is_invoke_dynamic() || - this_cp->tag_at(index).is_dynamic_constant()), "Corrupted constant pool"); - Handle bsm; - int argc; - { - // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&mtype], plus optional arguments - // JVM_CONSTANT_Dynamic is an ordered pair of [bootm, name&ftype], plus optional arguments - // In both cases, the bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry. - // It is accompanied by the optional arguments. - int bsm_index = this_cp->bootstrap_method_ref_index_at(index); - oop bsm_oop = this_cp->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL); - if (!java_lang_invoke_MethodHandle::is_instance(bsm_oop)) { - THROW_MSG_NULL(vmSymbols::java_lang_LinkageError(), "BSM not an MethodHandle"); - } - - // Extract the optional static arguments. - argc = this_cp->bootstrap_argument_count_at(index); - - // if there are no static arguments, return the bsm by itself: - if (argc == 0 && UseBootstrapCallInfo < 2) return bsm_oop; - - bsm = Handle(THREAD, bsm_oop); - } - - // We are going to return an ordered pair of {bsm, info}, using a 2-array. - objArrayHandle info; - { - objArrayOop info_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), 2, CHECK_NULL); - info = objArrayHandle(THREAD, info_oop); - } - - info->obj_at_put(0, bsm()); - - bool use_BSCI; - switch (UseBootstrapCallInfo) { - default: use_BSCI = true; break; // stress mode - case 0: use_BSCI = false; break; // stress mode - case 1: // normal mode - // If we were to support an alternative mode of BSM invocation, - // we'd convert to pull mode here if the BSM could be a candidate - // for that alternative mode. We can't easily test for things - // like varargs here, but we can get away with approximate testing, - // since the JDK runtime will make up the difference either way. - // For now, exercise the pull-mode path if the BSM is of arity 2, - // or if there is a potential condy loop (see below). - oop mt_oop = java_lang_invoke_MethodHandle::type(bsm()); - use_BSCI = (java_lang_invoke_MethodType::ptype_count(mt_oop) == 2); - break; - } - - // Here's a reason to use BSCI even if it wasn't requested: - // If a condy uses a condy argument, we want to avoid infinite - // recursion (condy loops) in the C code. It's OK in Java, - // because Java has stack overflow checking, so we punt - // potentially cyclic cases from C to Java. - if (!use_BSCI && this_cp->tag_at(index).is_dynamic_constant()) { - bool found_unresolved_condy = false; - for (int i = 0; i < argc; i++) { - int arg_index = this_cp->bootstrap_argument_index_at(index, i); - if (this_cp->tag_at(arg_index).is_dynamic_constant()) { - // potential recursion point condy -> condy - bool found_it = false; - this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL); - if (!found_it) { found_unresolved_condy = true; break; } - } - } - if (found_unresolved_condy) - use_BSCI = true; - } - - const int SMALL_ARITY = 5; - if (use_BSCI && argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) { - // If there are only a few arguments, and none of them need linking, - // push them, instead of asking the JDK runtime to turn around and - // pull them, saving a JVM/JDK transition in some simple cases. - bool all_resolved = true; - for (int i = 0; i < argc; i++) { - bool found_it = false; - int arg_index = this_cp->bootstrap_argument_index_at(index, i); - this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL); - if (!found_it) { all_resolved = false; break; } - } - if (all_resolved) - use_BSCI = false; - } - - if (!use_BSCI) { - // return {bsm, {arg...}}; resolution of arguments is done immediately, before JDK code is called - objArrayOop args_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), argc, CHECK_NULL); - info->obj_at_put(1, args_oop); // may overwrite with args[0] below - objArrayHandle args(THREAD, args_oop); - copy_bootstrap_arguments_at_impl(this_cp, index, 0, argc, args, 0, true, Handle(), CHECK_NULL); - if (argc == 1) { - // try to discard the singleton array - oop arg_oop = args->obj_at(0); - if (arg_oop != NULL && !arg_oop->is_array()) { - // JVM treats arrays and nulls specially in this position, - // but other things are just single arguments - info->obj_at_put(1, arg_oop); - } - } - } else { - // return {bsm, {arg_count, pool_index}}; JDK code must pull the arguments as needed - typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK_NULL); - ints_oop->int_at_put(0, argc); - ints_oop->int_at_put(1, index); - info->obj_at_put(1, ints_oop); - } - return info(); -} - void ConstantPool::copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index, int start_arg, int end_arg, objArrayHandle info, int pos, @@ -1848,8 +1730,8 @@ } // end compare_operand_to() // Search constant pool search_cp for a bootstrap specifier that matches -// this constant pool's bootstrap specifier at pattern_i index. -// Return the index of a matching bootstrap specifier or (-1) if there is no match. +// this constant pool's bootstrap specifier data at pattern_i index. +// Return the index of a matching bootstrap attribute record or (-1) if there is no match. int ConstantPool::find_matching_operand(int pattern_i, const constantPoolHandle& search_cp, int search_len, TRAPS) { for (int i = 0; i < search_len; i++) { @@ -1858,7 +1740,7 @@ return i; } } - return -1; // bootstrap specifier not found; return unused index (-1) + return -1; // bootstrap specifier data not found; return unused index (-1) } // end find_matching_operand()