7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites

Reviewed-by: kvn
This commit is contained in:
Christian Thalinger 2012-08-28 15:24:39 -07:00
parent 447e7065d2
commit 40c1bd4242
12 changed files with 164 additions and 181 deletions

View file

@ -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);)
}