< prev index next >

src/hotspot/share/oops/constantPool.cpp

Print this page

        

*** 28,48 **** #include "classfile/javaClasses.inline.hpp" #include "classfile/metadataOnStackMark.hpp" #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" #include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" - #include "memory/universe.hpp" #include "oops/array.hpp" #include "oops/constantPool.inline.hpp" #include "oops/cpCache.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" --- 28,46 ----
*** 369,401 **** resolved_references() != NULL ? resolved_references()->length() : 0); // If archiving heap objects is not allowed, clear the resolved references. // Otherwise, it is cleared after the resolved references array is cached // (see archive_resolved_references()). ! // If DynamicDumpSharedSpaces is enabled, clear the resolved references also ! // as java objects are not archived in the top layer. ! if (!HeapShared::is_heap_object_archiving_allowed() || DynamicDumpSharedSpaces) { set_resolved_references(NULL); } // Shared ConstantPools are in the RO region, so the _flags cannot be modified. // The _on_stack flag is used to prevent ConstantPools from deallocation during // class redefinition. Since shared ConstantPools cannot be deallocated anyway, // we always set _on_stack to true to avoid having to change _flags during runtime. _flags |= (_on_stack | _is_shared); int num_klasses = 0; for (int index = 1; index < length(); index++) { // Index 0 is unused ! if (!DynamicDumpSharedSpaces) { ! assert(!tag_at(index).is_unresolved_klass_in_error(), "This must not happen during static dump time"); ! } else { ! if (tag_at(index).is_unresolved_klass_in_error() || ! tag_at(index).is_method_handle_in_error() || ! tag_at(index).is_method_type_in_error() || ! tag_at(index).is_dynamic_constant_in_error()) { ! tag_at_put(index, JVM_CONSTANT_UnresolvedClass); ! } ! } if (tag_at(index).is_klass()) { // This class was resolved as a side effect of executing Java code // during dump time. We need to restore it back to an UnresolvedClass, // so that the proper class loading and initialization can happen // at runtime. --- 367,388 ---- resolved_references() != NULL ? resolved_references()->length() : 0); // If archiving heap objects is not allowed, clear the resolved references. // Otherwise, it is cleared after the resolved references array is cached // (see archive_resolved_references()). ! if (!HeapShared::is_heap_object_archiving_allowed()) { set_resolved_references(NULL); } // Shared ConstantPools are in the RO region, so the _flags cannot be modified. // The _on_stack flag is used to prevent ConstantPools from deallocation during // class redefinition. Since shared ConstantPools cannot be deallocated anyway, // we always set _on_stack to true to avoid having to change _flags during runtime. _flags |= (_on_stack | _is_shared); int num_klasses = 0; for (int index = 1; index < length(); index++) { // Index 0 is unused ! assert(!tag_at(index).is_unresolved_klass_in_error(), "This must not happen during dump time"); if (tag_at(index).is_klass()) { // This class was resolved as a side effect of executing Java code // during dump time. We need to restore it back to an UnresolvedClass, // so that the proper class loading and initialization can happen // at runtime.
*** 920,952 **** break; } case JVM_CONSTANT_Dynamic: { ! // 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 // method handle which will be the bootstrap method for the dynamically-computed // constant. If resolution of 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. No need to // set a DynamicConstantInError here since any subsequent use of this // bootstrap method will encounter the resolution of MethodHandleInError. ! // 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); } ! 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. const char* fail = NULL; if (result_oop == NULL) { --- 907,949 ---- break; } 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); // The initial step in resolving an unresolved symbolic reference to a // dynamically-computed constant is to resolve the symbolic reference to a // method handle which will be the bootstrap method for the dynamically-computed // constant. If resolution of 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. 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(); 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); if (!is_reference_type(type)) { // Make sure the primitive value is properly boxed. // This is a JDK responsibility. const char* fail = NULL; if (result_oop == NULL) {
*** 962,975 **** // but do not save a DynamicInError resolution result. // See section 5.4.3 of the VM spec. THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), fail); } } - - if (TraceMethodHandles) { - bootstrap_specifier.print_msg_on(tty, "resolve_constant_at_impl"); - } break; } case JVM_CONSTANT_String: assert(cache_index != _no_index_sentinel, "should have been set"); --- 959,968 ----
*** 1005,1025 **** // Check constant pool method consistency if ((callee->is_interface() && m_tag.is_method()) || ((!callee->is_interface() && m_tag.is_interface_method()))) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Inconsistent constant pool data in classfile for class %s. " ! "Method '", callee->name()->as_C_string()); ! signature->print_as_signature_external_return_type(&ss); ! ss.print(" %s(", name->as_C_string()); ! signature->print_as_signature_external_parameters(&ss); ! ss.print(")' at index %d is %s and should be %s", ! index, ! callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef", ! callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef"); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } Klass* klass = this_cp->pool_holder(); Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind, callee, name, signature, --- 998,1015 ---- // Check constant pool method consistency if ((callee->is_interface() && m_tag.is_method()) || ((!callee->is_interface() && m_tag.is_interface_method()))) { ResourceMark rm(THREAD); ! char buf[400]; ! jio_snprintf(buf, sizeof(buf), ! "Inconsistent constant pool data in classfile for class %s. " ! "Method %s%s at index %d is %s and should be %s", ! callee->name()->as_C_string(), name->as_C_string(), signature->as_C_string(), index, ! callee->is_interface() ? "CONSTANT_MethodRef" : "CONSTANT_InterfaceMethodRef", ! callee->is_interface() ? "CONSTANT_InterfaceMethodRef" : "CONSTANT_MethodRef"); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } Klass* klass = this_cp->pool_holder(); Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind, callee, name, signature,
*** 1107,1116 **** --- 1097,1219 ---- oop str = StringTable::intern(sym, CHECK_(NULL)); assert(java_lang_String::is_instance(str), "must be string"); 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, bool must_resolve, Handle if_not_available, TRAPS) {
*** 1740,1760 **** } return false; } // end compare_operand_to() // Search constant pool search_cp for a bootstrap specifier that matches ! // 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++) { bool found = compare_operand_to(pattern_i, search_cp, i, CHECK_(-1)); if (found) { return i; } } ! return -1; // bootstrap specifier data not found; return unused index (-1) } // end find_matching_operand() #ifndef PRODUCT --- 1843,1863 ---- } return false; } // 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. int ConstantPool::find_matching_operand(int pattern_i, const constantPoolHandle& search_cp, int search_len, TRAPS) { for (int i = 0; i < search_len; i++) { bool found = compare_operand_to(pattern_i, search_cp, i, CHECK_(-1)); if (found) { return i; } } ! return -1; // bootstrap specifier not found; return unused index (-1) } // end find_matching_operand() #ifndef PRODUCT
< prev index next >