Optimize JVM_GetDeclaringClass
David Holmes
david.holmes at oracle.com
Wed Jun 10 04:13:37 UTC 2020
Hi Christoph,
I have filed:
https://bugs.openjdk.java.net/browse/JDK-8247296
for this enhancement.
In general you need to be careful about exposing naked oops when
resolving these JNI handles, but it seems okay in this case.
I can also sponsor this for you, but there may be a short delay.
Cheers,
David
-----
On 10/06/2020 3:52 am, Christoph Dreis wrote:
> I've just stumbled upon JVM_GetDeclaringClass that I think could be optimized.
> The basic idea of the attached patch is to avoid repeated calls to JNIHandles::resolve_non_null & java_lang_Class::as_Klass.
>
> With the following benchmark:
>
> @BenchmarkMode(Mode.AverageTime)
> @OutputTimeUnit(TimeUnit.NANOSECONDS)
> public class MyBenchmark {
>
> @State(Scope.Benchmark)
> public static class ThreadState {
> private Class<?> clazz = ThreadState.class;
> }
>
> @Benchmark
> public Class<?> testClass(ThreadState threadState) {
> return threadState.clazz.getDeclaringClass();
> }
>
> }
>
> I see the following results:
>
> BEFORE
> Benchmark Mode Cnt Score Error Units
> MyBenchmark.testClass avgt 10 119,462 ± 3,914 ns/op
>
> PATCHED
> Benchmark Mode Cnt Score Error Units
> MyBenchmark.testClass avgt 10 102,457 ± 4,746 ns/op
>
> In case you think this is worthwhile, I would appreciate if someone can sponsor the patch.
>
> Let me know what you think & if I'm missing something (my C++ is a bit rusted).
> (Because there seem to be similar optimizations possible throughout jvm.cpp.)
>
> Cheers,
> Christoph
>
>
> ===== PATCH =====
>
> --- a/src/hotspot/share/prims/jvm.cpp Sat Jun 06 08:13:40 2020 +0000
> +++ b/src/hotspot/share/prims/jvm.cpp Tue Jun 09 19:41:02 2020 +0200
> @@ -1560,15 +1560,17 @@
> JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass))
> {
> // ofClass is a reference to a java_lang_Class object.
> - if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
> - ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) {
> + oop mirror = JNIHandles::resolve_non_null(ofClass);
> + if (java_lang_Class::is_primitive(mirror)) {
> + return NULL;
> + }
> + Klass* k = java_lang_Class::as_Klass(mirror);
> + if (!k->is_instance_klass()) {
> return NULL;
> }
>
> bool inner_is_member = false;
> - Klass* outer_klass
> - = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))
> - )->compute_enclosing_class(&inner_is_member, CHECK_NULL);
> + Klass* outer_klass = InstanceKlass::cast(k)->compute_enclosing_class(&inner_is_member, CHECK_NULL);
> if (outer_klass == NULL) return NULL; // already a top-level class
> if (!inner_is_member) return NULL; // a hidden or unsafe anonymous class (inside a method)
> return (jclass) JNIHandles::make_local(env, outer_klass->java_mirror());
More information about the hotspot-runtime-dev
mailing list