< prev index next >

src/hotspot/share/classfile/systemDictionary.cpp

Print this page
rev 52749 : Bootstrap method consolidation
* clean up and simplify JDK support code for BSM invocation
* simplify JVM bootstrap handshake: use BootstrapCallInfo only
* remove unused JVM paths and data fields
* move bootstrap argument processing from MethodHandleNatives to ConstantPool
* remove ConstantGroup; merge argument access into BootstrapCallInfo
* adjust BSM argument access: remove copyArguments, add argumentRef API
* add metadata-free BSM modes, including symbolic arguments from CP

*** 2510,2520 **** methodHandle SystemDictionary::find_method_handle_invoker(Klass* klass, Symbol* name, Symbol* signature, Klass* accessing_klass, Handle *appendix_result, - Handle *method_type_result, TRAPS) { methodHandle empty; assert(THREAD->can_call_java() ,""); Handle method_type = SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty)); --- 2510,2519 ----
*** 2543,2553 **** SystemDictionary::MethodHandleNatives_klass(), vmSymbols::linkMethod_name(), vmSymbols::linkMethod_signature(), &args, CHECK_(empty)); Handle mname(THREAD, (oop) result.get_jobject()); - (*method_type_result) = method_type; return unpack_method_and_appendix(mname, accessing_klass, appendix_box, appendix_result, THREAD); } // Decide if we can globally cache a lookup of this class, to be returned to any client that asks. // We must ensure that all class loaders everywhere will reach this class, for any client. --- 2542,2551 ----
*** 2584,2593 **** --- 2582,2592 ---- Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature, Klass* accessing_klass, Handle class_loader, Handle protection_domain, SignatureStream::FailureMode failure_mode, + bool check_access, TRAPS) { Handle empty; assert(accessing_klass == NULL || (class_loader.is_null() && protection_domain.is_null()), "one or the other, or perhaps neither");
*** 2624,2634 **** return Handle(); // report failure this way } Handle mirror(THREAD, constant_type_klass->java_mirror()); // Check accessibility, emulating ConstantPool::verify_constant_pool_resolve. ! if (accessing_klass != NULL) { Klass* sel_klass = constant_type_klass; bool fold_type_to_class = true; LinkResolver::check_klass_accessability(accessing_klass, sel_klass, fold_type_to_class, CHECK_(empty)); } --- 2623,2633 ---- return Handle(); // report failure this way } Handle mirror(THREAD, constant_type_klass->java_mirror()); // Check accessibility, emulating ConstantPool::verify_constant_pool_resolve. ! if (check_access && accessing_klass != NULL) { Klass* sel_klass = constant_type_klass; bool fold_type_to_class = true; LinkResolver::check_klass_accessability(accessing_klass, sel_klass, fold_type_to_class, CHECK_(empty)); }
*** 2732,2762 **** // report back to the caller with the MethodType return method_type; } - Handle SystemDictionary::find_field_handle_type(Symbol* signature, - Klass* accessing_klass, - TRAPS) { - Handle empty; - ResourceMark rm(THREAD); - SignatureStream ss(signature, /*is_method=*/ false); - if (!ss.is_done()) { - Handle class_loader, protection_domain; - if (accessing_klass != NULL) { - class_loader = Handle(THREAD, accessing_klass->class_loader()); - protection_domain = Handle(THREAD, accessing_klass->protection_domain()); - } - oop mirror = ss.as_java_mirror(class_loader, protection_domain, SignatureStream::NCDFError, CHECK_(empty)); - ss.next(); - if (ss.is_done()) { - return Handle(THREAD, mirror); - } - } - return empty; - } - // Ask Java code to find or construct a method handle constant. Handle SystemDictionary::link_method_handle_constant(Klass* caller, int ref_kind, //e.g., JVM_REF_invokeVirtual Klass* callee, Symbol* name, --- 2731,2740 ----
*** 2804,2915 **** vmSymbols::linkMethodHandleConstant_signature(), &args, CHECK_(empty)); return Handle(THREAD, (oop) result.get_jobject()); } ! // Ask Java to compute a constant by invoking a BSM given a Dynamic_info CP entry ! Handle SystemDictionary::link_dynamic_constant(Klass* caller, ! int condy_index, ! Handle bootstrap_specifier, ! Symbol* name, ! Symbol* type, ! TRAPS) { ! Handle empty; ! Handle bsm, info; ! if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) { ! bsm = bootstrap_specifier; ! } else { ! assert(bootstrap_specifier->is_objArray(), ""); ! objArrayOop args = (objArrayOop) bootstrap_specifier(); ! assert(args->length() == 2, ""); ! bsm = Handle(THREAD, args->obj_at(0)); ! info = Handle(THREAD, args->obj_at(1)); ! } ! guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()), ! "caller must supply a valid BSM"); ! ! // This should not happen. JDK code should take care of that. ! if (caller == NULL) { ! THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad dynamic constant", empty); } ! ! Handle constant_name = java_lang_String::create_from_symbol(name, CHECK_(empty)); ! ! // Resolve the constant type in the context of the caller class ! Handle type_mirror = find_java_mirror_for_type(type, caller, SignatureStream::NCDFError, ! CHECK_(empty)); ! ! // call java.lang.invoke.MethodHandleNatives::linkConstantDyanmic(caller, condy_index, bsm, type, info) ! JavaCallArguments args; ! args.push_oop(Handle(THREAD, caller->java_mirror())); ! args.push_int(condy_index); ! args.push_oop(bsm); ! args.push_oop(constant_name); ! args.push_oop(type_mirror); ! args.push_oop(info); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), ! vmSymbols::linkDynamicConstant_name(), ! vmSymbols::linkDynamicConstant_signature(), ! &args, CHECK_(empty)); ! ! return Handle(THREAD, (oop) result.get_jobject()); ! } ! ! // Ask Java code to find or construct a java.lang.invoke.CallSite for the given ! // name and signature, as interpreted relative to the given class loader. ! methodHandle SystemDictionary::find_dynamic_call_site_invoker(Klass* caller, ! int indy_index, ! Handle bootstrap_specifier, ! Symbol* name, ! Symbol* type, ! Handle *appendix_result, ! Handle *method_type_result, ! TRAPS) { ! methodHandle empty; ! Handle bsm, info; ! if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) { ! bsm = bootstrap_specifier; } else { ! objArrayOop args = (objArrayOop) bootstrap_specifier(); ! assert(args->length() == 2, ""); ! bsm = Handle(THREAD, args->obj_at(0)); ! info = Handle(THREAD, args->obj_at(1)); } - guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()), - "caller must supply a valid BSM"); - - Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty)); - Handle method_type = find_method_handle_type(type, caller, CHECK_(empty)); ! // This should not happen. JDK code should take care of that. ! if (caller == NULL || method_type.is_null()) { ! THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty); } - - objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty)); - assert(appendix_box->obj_at(0) == NULL, ""); - - // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, indy_index, bsm, name, mtype, info, &appendix) - JavaCallArguments args; - args.push_oop(Handle(THREAD, caller->java_mirror())); - args.push_int(indy_index); - args.push_oop(bsm); - args.push_oop(method_name); - args.push_oop(method_type); - args.push_oop(info); - args.push_oop(appendix_box); - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, - SystemDictionary::MethodHandleNatives_klass(), - vmSymbols::linkCallSite_name(), - vmSymbols::linkCallSite_signature(), - &args, CHECK_(empty)); - Handle mname(THREAD, (oop) result.get_jobject()); - (*method_type_result) = method_type; - return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD); } // Protection domain cache table handling ProtectionDomainCacheEntry* SystemDictionary::cache_get(Handle protection_domain) { --- 2782,2875 ---- vmSymbols::linkMethodHandleConstant_signature(), &args, CHECK_(empty)); return Handle(THREAD, (oop) result.get_jobject()); } ! // Ask Java to run a bootstrap method, in order to create a dynamic call site ! // while linking an invokedynamic op, or compute a constant for Dynamic_info CP entry ! // with linkage results being stored back into the bootstrap specifier. ! void SystemDictionary::invoke_bootstrap_method(BootstrapInfo& bootstrap_specifier, TRAPS) { ! ResourceMark rm; ! bootstrap_specifier.resolve_bsm(CHECK); ! bootstrap_specifier.resolve_metadata(CHECK); ! BootstrapInfo::BSMMode bsm_mode = bootstrap_specifier.bsm_mode(); ! ConstantPool::BootstrapArgumentReferenceMode arg_mode = ConstantPool::R_IFPRESENT; ! if (bsm_mode == BootstrapInfo::_metadata || ! (bsm_mode == BootstrapInfo::_expression && ! bootstrap_specifier.name() == vmSymbols::invoke_name())) ! // We know the BSM is going to immediately use all the arguments. ! arg_mode = ConstantPool::R_FORCE; ! // Otherwise, it can't hurt to pre-pack the object array with present arguments. ! bootstrap_specifier.resolve_args(arg_mode, CHECK); ! if (arg_mode != ConstantPool::R_FORCE) { ! // If we are going tentative, also grab the symbolic reference data. ! bootstrap_specifier.resolve_args(ConstantPool::R_SYMREF, CHECK); ! } ! ! Handle caller(THREAD, bootstrap_specifier.caller_mirror()); ! typeArrayOop index_info_oop = oopFactory::new_intArray(2, CHECK); ! typeArrayHandle index_info(THREAD, index_info_oop); ! index_info->int_at_put(0, bootstrap_specifier.argc()); ! index_info->int_at_put(1, bootstrap_specifier.bss_index()); ! ! bool has_appendix = bootstrap_specifier.is_method_call(); ! objArrayHandle appendix_box; ! if (has_appendix) { ! // Some method calls may require an appendix argument. Arrange to receive it. ! objArrayOop appendix_box_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK); ! appendix_box = objArrayHandle(THREAD, appendix_box_oop); ! assert(appendix_box->obj_at(0) == NULL, ""); } ! Handle request; ! if (bootstrap_specifier.indy_index() != 0) { ! // request is call-site specific ! request = Handle(THREAD, SystemDictionary::CallSite_klass()->java_mirror()); ! } ! ! Handle cpool = reflect_ConstantPool::create_from_pool(bootstrap_specifier.pool()(), CHECK); ! Handle arg_indexes(THREAD, bootstrap_specifier.arg_indexes()()); ! Handle arg_values(THREAD, bootstrap_specifier.arg_values()()); ! ! // call java.lang.invoke.MethodHandleNatives::bootstrapMethodHelper(cpool, bss_index, indy_index, argc, bsm, name, type, argIndexes, argValues, request, &appendix) ! JavaCallArguments args(11); ! args.push_oop(cpool); ! args.push_int(bootstrap_specifier.bss_index()); ! args.push_int(bootstrap_specifier.indy_index()); ! args.push_int(bootstrap_specifier.argc()); ! args.push_oop(bootstrap_specifier.bsm()); ! args.push_oop(bootstrap_specifier.name_arg()); ! args.push_oop(bootstrap_specifier.type_arg()); ! args.push_oop(bootstrap_specifier.arg_indexes()); ! args.push_oop(bootstrap_specifier.arg_values()); ! args.push_oop(request); ! args.push_oop(appendix_box); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), ! vmSymbols::bootstrapMethodHelper_name(), ! vmSymbols::bootstrapMethodHelper_signature(), ! &args, CHECK); ! if (has_appendix) { ! Handle appendix; ! Handle mname(THREAD, (oop) result.get_jobject()); ! methodHandle method = unpack_method_and_appendix(mname, ! bootstrap_specifier.caller(), ! appendix_box, ! &appendix, CHECK); ! bootstrap_specifier.set_resolved_method(method, appendix); } else { ! Handle value(THREAD, (oop) result.get_jobject()); ! bootstrap_specifier.set_resolved_value(value); } ! // sanity check ! if (!bootstrap_specifier.is_resolved() || ! (bootstrap_specifier.is_method_call() && ! bootstrap_specifier.resolved_method().is_null())) { ! // Could be a guarantee but throw IE instead, in case it is JDK bug. ! THROW_MSG(vmSymbols::java_lang_InternalError(), "bootstrap method call failed"); } } // Protection domain cache table handling ProtectionDomainCacheEntry* SystemDictionary::cache_get(Handle protection_domain) {
< prev index next >