8218994: Consolidate indy and condy JVM information within a BootstrapInfo data structure

Introduce BootstrapInfo data structure and merge invocation of a bootstrap method for condy and indy into invoke_bootstrap_method.

Co-authored-by: John Rose <john.r.rose@oracle.com>
Reviewed-by: acorn, coleenp
This commit is contained in:
Lois Foltan 2019-04-23 14:09:54 -04:00
parent fd3378a73e
commit 57aaf7a8cd
8 changed files with 534 additions and 325 deletions

View file

@ -2750,106 +2750,61 @@ Handle SystemDictionary::link_method_handle_constant(Klass* caller,
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");
// 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) {
// Resolve the bootstrap specifier, its name, type, and static arguments
bootstrap_specifier.resolve_bsm(CHECK);
// This should not happen. JDK code should take care of that.
if (caller == NULL) {
THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad dynamic constant", empty);
if (bootstrap_specifier.caller() == NULL || bootstrap_specifier.type_arg().is_null()) {
THROW_MSG(vmSymbols::java_lang_InternalError(), "Invalid bootstrap method invocation with no caller or type argument");
}
Handle constant_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
bool is_indy = bootstrap_specifier.is_method_call();
objArrayHandle appendix_box;
if (is_indy) {
// Some method calls may require an appendix argument. Arrange to receive it.
appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK);
assert(appendix_box->obj_at(0) == NULL, "");
}
// 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)
// call condy: java.lang.invoke.MethodHandleNatives::linkDynamicConstant(caller, condy_index, bsm, type, info)
// indy: 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(condy_index);
args.push_oop(bsm);
args.push_oop(constant_name);
args.push_oop(type_mirror);
args.push_oop(info);
args.push_oop(Handle(THREAD, bootstrap_specifier.caller_mirror()));
args.push_int(bootstrap_specifier.bss_index());
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_values());
if (is_indy) {
args.push_oop(appendix_box);
}
JavaValue result(T_OBJECT);
JavaCalls::call_static(&result,
SystemDictionary::MethodHandleNatives_klass(),
vmSymbols::linkDynamicConstant_name(),
vmSymbols::linkDynamicConstant_signature(),
&args, CHECK_(empty));
is_indy ? vmSymbols::linkCallSite_name() : vmSymbols::linkDynamicConstant_name(),
is_indy ? vmSymbols::linkCallSite_signature() : vmSymbols::linkDynamicConstant_signature(),
&args, CHECK);
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,
TRAPS) {
methodHandle empty;
Handle bsm, info;
if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) {
bsm = bootstrap_specifier;
Handle value(THREAD, (oop) result.get_jobject());
if (is_indy) {
Handle appendix;
methodHandle method = unpack_method_and_appendix(value,
bootstrap_specifier.caller(),
appendix_box,
&appendix, CHECK);
bootstrap_specifier.set_resolved_method(method, appendix);
} 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);
bootstrap_specifier.set_resolved_value(value);
}
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());
return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD);
// sanity check
assert(bootstrap_specifier.is_resolved() ||
(bootstrap_specifier.is_method_call() &&
bootstrap_specifier.resolved_method().not_null()), "bootstrap method call failed");
}
// Protection domain cache table handling