RFR: 8313332: Simplify lazy jmethodID cache in InstanceKlass
Serguei Spitsyn
sspitsyn at openjdk.org
Wed Apr 3 02:45:13 UTC 2024
On Fri, 29 Mar 2024 15:25:48 GMT, Coleen Phillimore <coleenp at openjdk.org> wrote:
> This change simplifies the code that grows the jmethodID cache in InstanceKlass. Instead of lazily, when there's a rare request for a jmethodID for an obsolete method, the jmethodID cache is grown during the RedefineClasses safepoint. The InstanceKlass's jmethodID cache is lazily allocated when there's a jmethodID allocated, so not every InstanceKlass has a cache, but the growth now only happens in a safepoint. This code will become racy with the potential change for deallocating jmethodIDs.
>
> Tested with tier1-4, vmTestbase/nsk/jvmti java/lang/instrument tests (in case they're not in tier1-4).
src/hotspot/share/oops/instanceKlass.cpp line 2277:
> 2275: jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) {
> 2276: Method* method = method_h();
> 2277: int idnum = method_h->method_idnum();
Nit: Can use `method` instead of `method_h()`.
src/hotspot/share/oops/instanceKlass.cpp line 2335:
> 2333: jmethodID new_id = Method::make_jmethod_id(class_loader_data(), method);
> 2334: Atomic::release_store(&jmeths[idnum+1], new_id);
> 2335: return new_id;
Nit: It feels like the function `InstanceKlass::get_jmethod_id()` can be more simplified with a small restructuring:
jmethodID update_jmethod_id(jmethodID* jmeths, Method* method, int idnum) {
// method_with_idnum
if (method->is_old() && !method->is_obsolete()) {
// The method passed in is old (but not obsolete), we need to use the current version
method = method_with_idnum((int)idnum);
assert(method != nullptr, "old and but not obsolete, so should exist");
}
jmethodID new_id = Method::make_jmethod_id(class_loader_data(), method);
Atomic::release_store(&jmeths[idnum+1], new_id);
return new_id;
}
jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) {
Method* method = method_h();
int idnum = method_h->method_idnum();
jmethodID* jmeths = methods_jmethod_ids_acquire();
<... big comment ...>
MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag);
if (jmeths == nullptr) {
jmeths = methods_jmethod_ids_acquire();
if (jmeths == nullptr) { // Still null?
size_t size = idnum_allocated_count();
assert(size > (size_t)idnum, "should already have space");
jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1, mtClass);
memset(jmeths, 0, (size+1)*sizeof(jmethodID));
// cache size is stored in element[0], other elements offset by one
jmeths[0] = (jmethodID)size;
jmethodID new_id = update_jmethod_id(jmeths, method, idnum);
// publish jmeths
release_set_methods_jmethod_ids(jmeths);
return new_id;
}
}
jmethodID id = Atomic::load_acquire(&jmeths[idnum+1]);
if (id == nullptr) {
id = jmeths[idnum+1];
if (id == nullptr) { // Still null?
jmethodID new_id = update_jmethod_id(jmeths, method, idnum);
return new_id;
}
}
return id;
}
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/18549#discussion_r1548840596
PR Review Comment: https://git.openjdk.org/jdk/pull/18549#discussion_r1548839930
More information about the serviceability-dev
mailing list