< prev index next >

src/hotspot/share/interpreter/linkResolver.cpp

Print this page

        

*** 30,46 **** #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" #include "gc/shared/collectedHeap.inline.hpp" - #include "interpreter/bootstrapInfo.hpp" #include "interpreter/bytecode.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/linkResolver.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" #include "oops/constantPool.hpp" #include "oops/cpCache.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/method.hpp" #include "oops/objArrayKlass.hpp" --- 30,46 ---- #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" #include "gc/shared/collectedHeap.inline.hpp" #include "interpreter/bytecode.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/linkResolver.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" + #include "memory/universe.hpp" #include "oops/constantPool.hpp" #include "oops/cpCache.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/method.hpp" #include "oops/objArrayKlass.hpp"
*** 262,271 **** --- 262,275 ---- // Coming from the constant pool always checks access _check_access = true; } + char* LinkInfo::method_string() const { + return Method::name_and_sig_as_C_string(_resolved_klass, _name, _signature); + } + #ifndef PRODUCT void LinkInfo::print() { ResourceMark rm; tty->print_cr("Link resolved_klass=%s name=%s signature=%s current_klass=%s check_access=%s", _resolved_klass->name()->as_C_string(),
*** 587,602 **** ResourceMark rm(THREAD); bool same_module = (sel_klass->module() == ref_klass->module()); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalAccessError(), ! "class %s tried to access %s%s%smethod '%s' (%s%s%s)", ref_klass->external_name(), sel_method->is_abstract() ? "abstract " : "", sel_method->is_protected() ? "protected " : "", sel_method->is_private() ? "private " : "", ! sel_method->external_name(), (same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(), (same_module) ? "" : "; ", (same_module) ? "" : sel_klass->class_in_module_of_loader() ); return; --- 591,608 ---- ResourceMark rm(THREAD); bool same_module = (sel_klass->module() == ref_klass->module()); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalAccessError(), ! "class %s tried to access %s%s%smethod %s.%s%s (%s%s%s)", ref_klass->external_name(), sel_method->is_abstract() ? "abstract " : "", sel_method->is_protected() ? "protected " : "", sel_method->is_private() ? "private " : "", ! sel_klass->external_name(), ! sel_method->name()->as_C_string(), ! sel_method->signature()->as_C_string(), (same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(), (same_module) ? "" : "; ", (same_module) ? "" : sel_klass->class_in_module_of_loader() ); return;
*** 662,676 **** Klass* resolved_method_class = resolved_method->method_holder(); ClassLoaderData* target_loader_data = resolved_method_class->class_loader_data(); assert(target_loader_data != NULL, "resolved method's class has no class loader data"); stringStream ss; ! ss.print("loader constraint violation: when resolving %s '", method_type); ! Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature()); ! ss.print("' the class loader %s of the current class, %s," " and the class loader %s for the method's defining class, %s, have" " different Class objects for the type %s used in the signature (%s; %s)", current_loader_data->loader_name_and_id(), current_class->name()->as_C_string(), target_loader_data->loader_name_and_id(), resolved_method_class->name()->as_C_string(), failed_type_symbol->as_C_string(), --- 668,683 ---- Klass* resolved_method_class = resolved_method->method_holder(); ClassLoaderData* target_loader_data = resolved_method_class->class_loader_data(); assert(target_loader_data != NULL, "resolved method's class has no class loader data"); stringStream ss; ! ss.print("loader constraint violation: when resolving %s" ! " \"%s\" the class loader %s of the current class, %s," " and the class loader %s for the method's defining class, %s, have" " different Class objects for the type %s used in the signature (%s; %s)", + method_type, + link_info.method_string(), current_loader_data->loader_name_and_id(), current_class->name()->as_C_string(), target_loader_data->loader_name_and_id(), resolved_method_class->name()->as_C_string(), failed_type_symbol->as_C_string(),
*** 730,744 **** } // 2. check constant pool tag for called method - must be JVM_CONSTANT_Methodref if (!link_info.tag().is_invalid() && !link_info.tag().is_method()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Method '"); ! Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature()); ! ss.print("' must be Methodref constant"); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } // 3. lookup method in resolved klass and its super klasses methodHandle resolved_method(THREAD, lookup_method_in_klasses(link_info, true, false)); --- 737,749 ---- } // 2. check constant pool tag for called method - must be JVM_CONSTANT_Methodref if (!link_info.tag().is_invalid() && !link_info.tag().is_method()) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), "Method %s must be Methodref constant", link_info.method_string()); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } // 3. lookup method in resolved klass and its super klasses methodHandle resolved_method(THREAD, lookup_method_in_klasses(link_info, true, false));
*** 757,772 **** } // 5. method lookup failed if (resolved_method.is_null()) { ResourceMark rm(THREAD); - stringStream ss; - ss.print("'"); - Method::print_external_name(&ss, resolved_klass, link_info.name(), link_info.signature()); - ss.print("'"); THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(), ! ss.as_string(), nested_exception, NULL); } // 6. access checks, access checking may be turned off when calling from within the VM. Klass* current_klass = link_info.current_klass(); if (link_info.check_access()) { --- 762,776 ---- } // 5. method lookup failed if (resolved_method.is_null()) { ResourceMark rm(THREAD); THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(), ! Method::name_and_sig_as_C_string(resolved_klass, ! link_info.name(), ! link_info.signature()), ! nested_exception, NULL); } // 6. access checks, access checking may be turned off when calling from within the VM. Klass* current_klass = link_info.current_klass(); if (link_info.check_access()) {
*** 834,848 **** } // check constant pool tag for called method - must be JVM_CONSTANT_InterfaceMethodref if (!link_info.tag().is_invalid() && !link_info.tag().is_interface_method()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Method '"); ! Method::print_external_name(&ss, link_info.resolved_klass(), link_info.name(), link_info.signature()); ! ss.print("' must be InterfaceMethodref constant"); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } // lookup method in this interface or its super, java.lang.Object // JDK8: also look for static methods methodHandle resolved_method(THREAD, lookup_method_in_klasses(link_info, false, true)); --- 838,850 ---- } // check constant pool tag for called method - must be JVM_CONSTANT_InterfaceMethodref if (!link_info.tag().is_invalid() && !link_info.tag().is_interface_method()) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), "Method %s must be InterfaceMethodref constant", link_info.method_string()); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } // lookup method in this interface or its super, java.lang.Object // JDK8: also look for static methods methodHandle resolved_method(THREAD, lookup_method_in_klasses(link_info, false, true));
*** 853,867 **** } if (resolved_method.is_null()) { // no method found ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("'"); ! Method::print_external_name(&ss, resolved_klass, link_info.name(), link_info.signature()); ! ss.print("'"); ! THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), ss.as_string()); } if (link_info.check_access()) { // JDK8 adds non-public interface methods, and accessability check requirement Klass* current_klass = link_info.current_klass(); --- 855,868 ---- } if (resolved_method.is_null()) { // no method found ResourceMark rm(THREAD); ! THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), ! Method::name_and_sig_as_C_string(resolved_klass, ! link_info.name(), ! link_info.signature())); } if (link_info.check_access()) { // JDK8 adds non-public interface methods, and accessability check requirement Klass* current_klass = link_info.current_klass();
*** 878,893 **** check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL); } if (code != Bytecodes::_invokestatic && resolved_method->is_static()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Expected instance not static method '"); ! Method::print_external_name(&ss, resolved_klass, ! resolved_method->name(), resolved_method->signature()); ! ss.print("'"); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } if (log_develop_is_enabled(Trace, itables)) { char buf[200]; jio_snprintf(buf, sizeof(buf), "%s resolved interface method: caller-class:", --- 879,893 ---- check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL); } if (code != Bytecodes::_invokestatic && resolved_method->is_static()) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", ! Method::name_and_sig_as_C_string(resolved_klass, ! resolved_method->name(), resolved_method->signature())); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } if (log_develop_is_enabled(Trace, itables)) { char buf[200]; jio_snprintf(buf, sizeof(buf), "%s resolved interface method: caller-class:",
*** 1084,1098 **** assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); // check if static if (!resolved_method->is_static()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Expected static method '"); ! resolved_method()->print_external_name(&ss); ! ss.print("'"); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } return resolved_method; } --- 1084,1098 ---- assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); // check if static if (!resolved_method->is_static()) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), "Expected static method %s", Method::name_and_sig_as_C_string(resolved_klass, ! resolved_method->name(), ! resolved_method->signature())); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } return resolved_method; }
*** 1125,1144 **** // check if method name is <init>, that it is found in same klass as static type if (resolved_method->name() == vmSymbols::object_initializer_name() && resolved_method->method_holder() != resolved_klass) { ResourceMark rm(THREAD); - stringStream ss; - ss.print("%s: method '", resolved_klass->external_name()); - resolved_method->signature()->print_as_signature_external_return_type(&ss); - ss.print(" %s(", resolved_method->name()->as_C_string()); - resolved_method->signature()->print_as_signature_external_parameters(&ss); - ss.print(")' not found"); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_NoSuchMethodError(), ! "%s", ss.as_string()); return NULL; } // ensure that invokespecial's interface method reference is in // a direct superinterface, not an indirect superinterface --- 1125,1142 ---- // check if method name is <init>, that it is found in same klass as static type if (resolved_method->name() == vmSymbols::object_initializer_name() && resolved_method->method_holder() != resolved_klass) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, vmSymbols::java_lang_NoSuchMethodError(), ! "%s: method %s%s not found", ! resolved_klass->external_name(), ! resolved_method->name()->as_C_string(), ! resolved_method->signature()->as_C_string() ! ); return NULL; } // ensure that invokespecial's interface method reference is in // a direct superinterface, not an indirect superinterface
*** 1153,1179 **** SystemDictionary::reflect_MagicAccessorImpl_klass()); if (!is_reflect && !klass_to_check->is_same_or_direct_interface(resolved_klass)) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Interface method reference: '"); ! resolved_method->print_external_name(&ss); ! ss.print("', is in an indirect superinterface of %s", ! current_klass->external_name()); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } } // check if not static if (resolved_method->is_static()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Expecting non-static method '"); ! resolved_method->print_external_name(&ss); ! ss.print("'"); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } if (log_develop_is_enabled(Trace, itables)) { trace_method_resolution("invokespecial resolved method: caller-class:", current_klass, resolved_klass, resolved_method, true); --- 1151,1181 ---- SystemDictionary::reflect_MagicAccessorImpl_klass()); if (!is_reflect && !klass_to_check->is_same_or_direct_interface(resolved_klass)) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), ! "Interface method reference: %s, is in an indirect superinterface of %s", ! Method::name_and_sig_as_C_string(resolved_klass, ! resolved_method->name(), ! resolved_method->signature()), ! current_klass->external_name()); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } } // check if not static if (resolved_method->is_static()) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), ! "Expecting non-static method %s", ! Method::name_and_sig_as_C_string(resolved_klass, ! resolved_method->name(), ! resolved_method->signature())); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } if (log_develop_is_enabled(Trace, itables)) { trace_method_resolution("invokespecial resolved method: caller-class:", current_klass, resolved_klass, resolved_method, true);
*** 1215,1229 **** resolved_method->signature(), Klass::find_private, CHECK); // check if found if (sel_method.is_null()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("'"); ! resolved_method->print_external_name(&ss); ! ss.print("'"); ! THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string()); // check loader constraints if found a different method } else if (sel_method() != resolved_method()) { check_method_loader_constraints(link_info, sel_method, "method", CHECK); } } --- 1217,1230 ---- resolved_method->signature(), Klass::find_private, CHECK); // check if found if (sel_method.is_null()) { ResourceMark rm(THREAD); ! THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ! Method::name_and_sig_as_C_string(resolved_klass, ! resolved_method->name(), ! resolved_method->signature())); // check loader constraints if found a different method } else if (sel_method() != resolved_method()) { check_method_loader_constraints(link_info, sel_method, "method", CHECK); } }
*** 1241,1275 **** if (!receiver_klass->is_subtype_of(sender)) { ResourceMark rm(THREAD); char buf[500]; jio_snprintf(buf, sizeof(buf), "Receiver class %s must be the current class or a subtype of interface %s", ! receiver_klass->external_name(), ! sender->external_name()); THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), buf); } } } // check if not static if (sel_method->is_static()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Expecting non-static method '"); ! resolved_method->print_external_name(&ss); ! ss.print("'"); ! THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } // check if abstract if (sel_method->is_abstract()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("'"); ! Method::print_external_name(&ss, resolved_klass, sel_method->name(), sel_method->signature()); ! ss.print("'"); ! THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string()); } if (log_develop_is_enabled(Trace, itables)) { trace_method_resolution("invokespecial selected method: resolved-class:", resolved_klass, resolved_klass, sel_method, true); --- 1242,1275 ---- if (!receiver_klass->is_subtype_of(sender)) { ResourceMark rm(THREAD); char buf[500]; jio_snprintf(buf, sizeof(buf), "Receiver class %s must be the current class or a subtype of interface %s", ! receiver_klass->name()->as_C_string(), ! sender->name()->as_C_string()); THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), buf); } } } // check if not static if (sel_method->is_static()) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass, ! resolved_method->name(), ! resolved_method->signature())); ! THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } // check if abstract if (sel_method->is_abstract()) { ResourceMark rm(THREAD); ! THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ! Method::name_and_sig_as_C_string(resolved_klass, ! sel_method->name(), ! sel_method->signature())); } if (log_develop_is_enabled(Trace, itables)) { trace_method_resolution("invokespecial selected method: resolved-class:", resolved_klass, resolved_klass, sel_method, true);
*** 1303,1328 **** Klass* current_klass = link_info.current_klass(); // This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method if (resolved_klass->is_interface() && resolved_method->is_private()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("private interface method requires invokespecial, not invokevirtual: method '"); ! resolved_method->print_external_name(&ss); ! ss.print("', caller-class: %s", ! (current_klass == NULL ? "<null>" : current_klass->internal_name())); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } // check if not static if (resolved_method->is_static()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("Expecting non-static method '"); ! resolved_method->print_external_name(&ss); ! ss.print("'"); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string()); } if (log_develop_is_enabled(Trace, vtables)) { trace_method_resolution("invokevirtual resolved method: caller-class:", current_klass, resolved_klass, resolved_method, false); --- 1303,1329 ---- Klass* current_klass = link_info.current_klass(); // This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method if (resolved_klass->is_interface() && resolved_method->is_private()) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s", ! Method::name_and_sig_as_C_string(resolved_klass, ! resolved_method->name(), ! resolved_method->signature()), ! (current_klass == NULL ? "<NULL>" : current_klass->internal_name())); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } // check if not static if (resolved_method->is_static()) { ResourceMark rm(THREAD); ! char buf[200]; ! jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass, ! resolved_method->name(), ! resolved_method->signature())); ! THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); } if (log_develop_is_enabled(Trace, vtables)) { trace_method_resolution("invokevirtual resolved method: caller-class:", current_klass, resolved_klass, resolved_method, false);
*** 1467,1481 **** } // check access // Throw Illegal Access Error if selected_method is not public. if (!selected_method->is_public()) { ResourceMark rm(THREAD); ! stringStream ss; ! ss.print("'"); ! Method::print_external_name(&ss, recv_klass, selected_method->name(), selected_method->signature()); ! ss.print("'"); ! THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string()); } // check if abstract if (check_null_and_abstract && selected_method->is_abstract()) { throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK); } --- 1468,1481 ---- } // check access // Throw Illegal Access Error if selected_method is not public. if (!selected_method->is_public()) { ResourceMark rm(THREAD); ! THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ! Method::name_and_sig_as_C_string(recv_klass, ! selected_method->name(), ! selected_method->signature())); } // check if abstract if (check_null_and_abstract && selected_method->is_abstract()) { throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK); }
*** 1692,1775 **** Handle resolved_appendix; methodHandle resolved_method = lookup_polymorphic_method(link_info, &resolved_appendix, CHECK); result.set_handle(resolved_klass, resolved_method, resolved_appendix, CHECK); } ! void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int indy_index, TRAPS) { ! ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(indy_index); ! int pool_index = cpce->constant_pool_index(); // Resolve the bootstrap specifier (BSM + optional arguments). ! BootstrapInfo bootstrap_specifier(pool, pool_index, indy_index); ! ! // Check if CallSite has been bound already or failed already, and short circuit: ! { ! bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(result, CHECK); ! if (is_done) return; ! } ! ! // 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. ! resolve_dynamic_call(result, bootstrap_specifier, CHECK); if (TraceMethodHandles) { ! bootstrap_specifier.print_msg_on(tty, "resolve_invokedynamic"); } - - // The returned linkage result is provisional up to the moment - // the interpreter or runtime performs a serialized check of - // the relevant CPCE::f1 field. This is done by the caller - // of this method, via CPCE::set_dynamic_call, which uses - // an ObjectLocker to do the final serialization of updates - // to CPCE state, including f1. } void LinkResolver::resolve_dynamic_call(CallInfo& result, ! BootstrapInfo& bootstrap_specifier, TRAPS) { ! // JSR 292: this must resolve to an implicitly generated method ! // such as MH.linkToCallSite(*...) or some other call-site shape. // The appendix argument is likely to be a freshly-created CallSite. ! // It may also be a MethodHandle from an unwrapped ConstantCallSite, ! // or any other reference. The resolved_method as well as the appendix ! // are both recorded together via CallInfo::set_handle. ! SystemDictionary::invoke_bootstrap_method(bootstrap_specifier, THREAD); ! Exceptions::wrap_dynamic_exception(THREAD); ! ! if (HAS_PENDING_EXCEPTION) { ! if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { ! // Let any random low-level IE or SOE or OOME just bleed through. ! // Basically we pretend that the bootstrap method was never called, ! // if it fails this way: We neither record a successful linkage, ! // nor do we memorize a LE for posterity. ! return; ! } ! // JVMS 5.4.3 says: If an attempt by the Java Virtual Machine to resolve ! // a symbolic reference fails because an error is thrown that is an ! // instance of LinkageError (or a subclass), then subsequent attempts to ! // resolve the reference always fail with the same error that was thrown ! // as a result of the initial resolution attempt. ! bool recorded_res_status = bootstrap_specifier.save_and_throw_indy_exc(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. ! bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(result, CHECK); ! if (is_done) return; ! } ! assert(bootstrap_specifier.invokedynamic_cp_cache_entry()->indy_resolution_failed(), ! "Resolution failure flag wasn't set"); ! } ! ! bootstrap_specifier.resolve_newly_linked_invokedynamic(result, CHECK); ! // Exceptions::wrap_dynamic_exception not used because ! // set_handle doesn't throw linkage errors } // Selected method is abstract. void LinkResolver::throw_abstract_method_error(const methodHandle& resolved_method, const methodHandle& selected_method, --- 1692,1794 ---- Handle resolved_appendix; methodHandle resolved_method = lookup_polymorphic_method(link_info, &resolved_appendix, CHECK); result.set_handle(resolved_klass, resolved_method, resolved_appendix, CHECK); } ! void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { ! Symbol* method_name = pool->name_ref_at(index); ! Symbol* method_signature = pool->signature_ref_at(index); ! Klass* current_klass = pool->pool_holder(); // Resolve the bootstrap specifier (BSM + optional arguments). ! 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()) { ! 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); ! Exceptions::wrap_dynamic_exception(CHECK); ! assert(bsm_info != NULL, ""); ! // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic. ! bootstrap_specifier = Handle(THREAD, bsm_info); ! } ! if (!cpce->is_f1_null()) { ! methodHandle method( THREAD, cpce->f1_as_method()); ! Handle appendix( THREAD, cpce->appendix_if_resolved(pool)); ! result.set_handle(method, appendix, THREAD); ! Exceptions::wrap_dynamic_exception(CHECK); ! return; ! } if (TraceMethodHandles) { ! ResourceMark rm(THREAD); ! tty->print_cr("resolve_invokedynamic #%d %s %s in %s", ! ConstantPool::decode_invokedynamic_index(index), ! method_name->as_C_string(), method_signature->as_C_string(), ! current_klass->name()->as_C_string()); ! tty->print(" BSM info: "); bootstrap_specifier->print(); ! } ! ! resolve_dynamic_call(result, pool_index, 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)); ! result.set_handle(method, appendix, THREAD); ! Exceptions::wrap_dynamic_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, ! int pool_index, ! Handle bootstrap_specifier, ! Symbol* method_name, Symbol* method_signature, ! Klass* current_klass, TRAPS) { ! // JSR 292: this must resolve to an implicitly generated method MH.linkToCallSite(*...) // The appendix argument is likely to be a freshly-created CallSite. ! Handle resolved_appendix; ! methodHandle resolved_method = ! SystemDictionary::find_dynamic_call_site_invoker(current_klass, ! pool_index, ! bootstrap_specifier, ! method_name, method_signature, ! &resolved_appendix, ! THREAD); ! Exceptions::wrap_dynamic_exception(CHECK); ! result.set_handle(resolved_method, resolved_appendix, THREAD); ! Exceptions::wrap_dynamic_exception(CHECK); } // Selected method is abstract. void LinkResolver::throw_abstract_method_error(const methodHandle& resolved_method, const methodHandle& selected_method,
*** 1785,1809 **** } else { ss.print("Missing implementation of"); } assert(resolved_method.not_null(), "Sanity"); ! ss.print(" resolved method '%s%s", resolved_method->is_abstract() ? "abstract " : "", ! resolved_method->is_private() ? "private " : ""); ! resolved_method->signature()->print_as_signature_external_return_type(&ss); ! ss.print(" %s(", resolved_method->name()->as_C_string()); ! resolved_method->signature()->print_as_signature_external_parameters(&ss); ! ss.print(")' of %s %s.", resolved_klass->external_kind(), resolved_klass->external_name()); if (selected_method.not_null() && !(resolved_method == selected_method)) { ! ss.print(" Selected method is '%s%s", selected_method->is_abstract() ? "abstract " : "", ! selected_method->is_private() ? "private " : ""); ! selected_method->print_external_name(&ss); ! ss.print("'."); } THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string()); } --- 1804,1825 ---- } else { ss.print("Missing implementation of"); } assert(resolved_method.not_null(), "Sanity"); ! ss.print(" resolved method %s%s%s%s of %s %s.", resolved_method->is_abstract() ? "abstract " : "", ! resolved_method->is_private() ? "private " : "", ! resolved_method->name()->as_C_string(), ! resolved_method->signature()->as_C_string(), resolved_klass->external_kind(), resolved_klass->external_name()); if (selected_method.not_null() && !(resolved_method == selected_method)) { ! ss.print(" Selected method is %s%s%s.", selected_method->is_abstract() ? "abstract " : "", ! selected_method->is_private() ? "private " : "", ! selected_method->name_and_sig_as_C_string()); } THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string()); }
< prev index next >