8291736: find_method_handle_intrinsic leaks Method*

Reviewed-by: hseigel, iklam, dholmes
This commit is contained in:
Coleen Phillimore 2022-09-06 14:01:17 +00:00
parent b2067e63da
commit c05015bc93

View File

@ -2036,47 +2036,46 @@ Method* SystemDictionary::find_method_handle_intrinsic(vmIntrinsicID iid,
Symbol* signature,
TRAPS) {
methodHandle empty;
const int iid_as_int = vmIntrinsics::as_int(iid);
assert(MethodHandles::is_signature_polymorphic(iid) &&
MethodHandles::is_signature_polymorphic_intrinsic(iid) &&
iid != vmIntrinsics::_invokeGeneric,
"must be a known MH intrinsic iid=%d: %s", iid_as_int, vmIntrinsics::name_at(iid));
Method** met;
InvokeMethodKey key(signature, iid_as_int);
{
MutexLocker ml(THREAD, InvokeMethodTable_lock);
met = _invoke_method_intrinsic_table.get(key);
InvokeMethodKey key(signature, iid_as_int);
Method** met = _invoke_method_intrinsic_table.get(key);
if (met != nullptr) {
return *met;
}
bool throw_error = false;
// This function could get an OOM but it is safe to call inside of a lock because
// throwing OutOfMemoryError doesn't call Java code.
methodHandle m = Method::make_method_handle_intrinsic(iid, signature, CHECK_NULL);
if (!Arguments::is_interpreter_only() || iid == vmIntrinsics::_linkToNative) {
// Generate a compiled form of the MH intrinsic
// linkToNative doesn't have interpreter-specific implementation, so always has to go through compiled version.
AdapterHandlerLibrary::create_native_wrapper(m);
// Check if have the compiled code.
throw_error = (!m->has_compiled_code());
}
if (!throw_error) {
signature->make_permanent(); // The signature is never unloaded.
bool created = _invoke_method_intrinsic_table.put(key, m());
assert(created, "must be since we still hold the lock");
assert(Arguments::is_interpreter_only() || (m->has_compiled_code() &&
m->code()->entry_point() == m->from_compiled_entry()),
"MH intrinsic invariant");
return m();
}
}
methodHandle m = Method::make_method_handle_intrinsic(iid, signature, CHECK_NULL);
if (!Arguments::is_interpreter_only() || iid == vmIntrinsics::_linkToNative) {
// Generate a compiled form of the MH intrinsic
// linkToNative doesn't have interpreter-specific implementation, so always has to go through compiled version.
AdapterHandlerLibrary::create_native_wrapper(m);
// Check if have the compiled code.
if (!m->has_compiled_code()) {
THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(),
"Out of space in CodeCache for method handle intrinsic");
}
}
// Now grab the lock. We might have to throw away the new method,
// if a racing thread has managed to install one at the same time.
{
MutexLocker ml(THREAD, InvokeMethodTable_lock);
signature->make_permanent(); // The signature is never unloaded.
bool created;
met = _invoke_method_intrinsic_table.put_if_absent(key, m(), &created);
Method* saved_method = *met;
assert(Arguments::is_interpreter_only() || (saved_method->has_compiled_code() &&
saved_method->code()->entry_point() == saved_method->from_compiled_entry()),
"MH intrinsic invariant");
return saved_method;
}
// Throw error outside of the lock.
THROW_MSG_NULL(vmSymbols::java_lang_VirtualMachineError(),
"Out of space in CodeCache for method handle intrinsic");
}
// Helper for unpacking the return value from linkMethod and linkCallSite.