Optimize JVM_GetDeclaringClass

Christoph Dreis christoph.dreis at freenet.de
Tue Jun 9 17:52:41 UTC 2020


Hi,

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