mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-22 03:54:33 +02:00
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
Reviewed-by: kvn
This commit is contained in:
parent
447e7065d2
commit
40c1bd4242
12 changed files with 164 additions and 181 deletions
|
@ -738,91 +738,81 @@ methodOop ciEnv::lookup_method(instanceKlass* accessor,
|
|||
ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
|
||||
int index, Bytecodes::Code bc,
|
||||
ciInstanceKlass* accessor) {
|
||||
int holder_index = cpool->klass_ref_index_at(index);
|
||||
bool holder_is_accessible;
|
||||
ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
|
||||
ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
|
||||
if (bc == Bytecodes::_invokedynamic) {
|
||||
ConstantPoolCacheEntry* secondary_entry = cpool->cache()->secondary_entry_at(index);
|
||||
const bool is_resolved = !secondary_entry->is_f1_null();
|
||||
// FIXME: code generation could allow for null (unlinked) call site
|
||||
// The call site could be made patchable as follows:
|
||||
// Load the appendix argument from the constant pool.
|
||||
// Test the appendix argument and jump to a known deopt routine if it is null.
|
||||
// Jump through a patchable call site, which is initially a deopt routine.
|
||||
// Patch the call site to the nmethod entry point of the static compiled lambda form.
|
||||
// As with other two-component call sites, both values must be independently verified.
|
||||
|
||||
// Get the method's name and signature.
|
||||
Symbol* name_sym = cpool->name_ref_at(index);
|
||||
Symbol* sig_sym = cpool->signature_ref_at(index);
|
||||
|
||||
if (cpool->has_preresolution()
|
||||
|| (holder == ciEnv::MethodHandle_klass() &&
|
||||
MethodHandles::is_signature_polymorphic_name(holder->get_klassOop(), name_sym))) {
|
||||
// Short-circuit lookups for JSR 292-related call sites.
|
||||
// That is, do not rely only on name-based lookups, because they may fail
|
||||
// if the names are not resolvable in the boot class loader (7056328).
|
||||
switch (bc) {
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokeinterface:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
{
|
||||
oop appendix_oop = NULL;
|
||||
methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index);
|
||||
if (m != NULL) {
|
||||
return get_object(m)->as_method();
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (is_resolved) {
|
||||
// Get the invoker methodOop and the extra argument from the constant pool.
|
||||
methodOop adapter = secondary_entry->f2_as_vfinal_method();
|
||||
return get_object(adapter)->as_method();
|
||||
}
|
||||
}
|
||||
|
||||
if (holder_is_accessible) { // Our declared holder is loaded.
|
||||
instanceKlass* lookup = declared_holder->get_instanceKlass();
|
||||
methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
|
||||
if (m != NULL &&
|
||||
(bc == Bytecodes::_invokestatic
|
||||
? instanceKlass::cast(m->method_holder())->is_not_initialized()
|
||||
: !instanceKlass::cast(m->method_holder())->is_loaded())) {
|
||||
m = NULL;
|
||||
}
|
||||
if (m != NULL) {
|
||||
// We found the method.
|
||||
return get_object(m)->as_method();
|
||||
}
|
||||
}
|
||||
|
||||
// Either the declared holder was not loaded, or the method could
|
||||
// not be found. Create a dummy ciMethod to represent the failed
|
||||
// lookup.
|
||||
ciSymbol* name = get_symbol(name_sym);
|
||||
ciSymbol* signature = get_symbol(sig_sym);
|
||||
return get_unloaded_method(declared_holder, name, signature, accessor);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciEnv::get_fake_invokedynamic_method_impl
|
||||
ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
||||
int index, Bytecodes::Code bc,
|
||||
ciInstanceKlass* accessor) {
|
||||
// Compare the following logic with InterpreterRuntime::resolve_invokedynamic.
|
||||
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
|
||||
|
||||
ConstantPoolCacheEntry* secondary_entry = cpool->cache()->secondary_entry_at(index);
|
||||
bool is_resolved = !secondary_entry->is_f1_null();
|
||||
// FIXME: code generation could allow for null (unlinked) call site
|
||||
// The call site could be made patchable as follows:
|
||||
// Load the appendix argument from the constant pool.
|
||||
// Test the appendix argument and jump to a known deopt routine if it is null.
|
||||
// Jump through a patchable call site, which is initially a deopt routine.
|
||||
// Patch the call site to the nmethod entry point of the static compiled lambda form.
|
||||
// As with other two-component call sites, both values must be independently verified.
|
||||
|
||||
// Call site might not be resolved yet.
|
||||
// Stop the code path here with an unlinked method.
|
||||
if (!is_resolved) {
|
||||
// Fake a method that is equivalent to a declared method.
|
||||
ciInstanceKlass* holder = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass();
|
||||
ciSymbol* name = ciSymbol::invokeBasic_name();
|
||||
ciSymbol* signature = get_symbol(cpool->signature_ref_at(index));
|
||||
return get_unloaded_method(holder, name, signature, accessor);
|
||||
}
|
||||
} else {
|
||||
const int holder_index = cpool->klass_ref_index_at(index);
|
||||
bool holder_is_accessible;
|
||||
ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
|
||||
ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
|
||||
|
||||
// Get the invoker methodOop and the extra argument from the constant pool.
|
||||
methodOop adapter = secondary_entry->f2_as_vfinal_method();
|
||||
return get_object(adapter)->as_method();
|
||||
// Get the method's name and signature.
|
||||
Symbol* name_sym = cpool->name_ref_at(index);
|
||||
Symbol* sig_sym = cpool->signature_ref_at(index);
|
||||
|
||||
if (cpool->has_preresolution()
|
||||
|| (holder == ciEnv::MethodHandle_klass() &&
|
||||
MethodHandles::is_signature_polymorphic_name(holder->get_klassOop(), name_sym))) {
|
||||
// Short-circuit lookups for JSR 292-related call sites.
|
||||
// That is, do not rely only on name-based lookups, because they may fail
|
||||
// if the names are not resolvable in the boot class loader (7056328).
|
||||
switch (bc) {
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokeinterface:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
{
|
||||
methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index);
|
||||
if (m != NULL) {
|
||||
return get_object(m)->as_method();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (holder_is_accessible) { // Our declared holder is loaded.
|
||||
instanceKlass* lookup = declared_holder->get_instanceKlass();
|
||||
methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
|
||||
if (m != NULL &&
|
||||
(bc == Bytecodes::_invokestatic
|
||||
? instanceKlass::cast(m->method_holder())->is_not_initialized()
|
||||
: !instanceKlass::cast(m->method_holder())->is_loaded())) {
|
||||
m = NULL;
|
||||
}
|
||||
if (m != NULL) {
|
||||
// We found the method.
|
||||
return get_object(m)->as_method();
|
||||
}
|
||||
}
|
||||
|
||||
// Either the declared holder was not loaded, or the method could
|
||||
// not be found. Create a dummy ciMethod to represent the failed
|
||||
// lookup.
|
||||
ciSymbol* name = get_symbol(name_sym);
|
||||
ciSymbol* signature = get_symbol(sig_sym);
|
||||
return get_unloaded_method(declared_holder, name, signature, accessor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -853,11 +843,7 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m
|
|||
ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
|
||||
int index, Bytecodes::Code bc,
|
||||
ciInstanceKlass* accessor) {
|
||||
if (bc == Bytecodes::_invokedynamic) {
|
||||
GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc, accessor);)
|
||||
} else {
|
||||
GUARDED_VM_ENTRY(return get_method_by_index_impl( cpool, index, bc, accessor);)
|
||||
}
|
||||
GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);)
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue