You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/06/26 02:03:17 UTC

[groovy] 01/01: Trivial tweak: avoid creating method handle repeatedly

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch danielsun/trivial-tweak-20210626
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 23ca7082eee393b6d9a5e00dfce5270a80686f14
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat Jun 26 10:02:09 2021 +0800

    Trivial tweak: avoid creating method handle repeatedly
---
 src/main/java/groovy/lang/MetaClassImpl.java | 88 +++++++++++++++-------------
 1 file changed, 47 insertions(+), 41 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java
index e8068f2..1f23830 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -115,6 +115,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
 
 import static groovy.lang.Tuple.tuple;
 import static java.lang.Character.isUpperCase;
@@ -122,6 +123,7 @@ import static org.apache.groovy.util.Arrays.concat;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
 import static org.codehaus.groovy.reflection.ReflectionCache.isAssignableFrom;
 import static org.codehaus.groovy.reflection.ReflectionUtils.parameterTypeMatches;
+import static org.codehaus.groovy.runtime.MetaClassHelper.castArgumentsToClassArray;
 
 /**
  * Allows methods to be dynamically added to existing classes at runtime
@@ -262,7 +264,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
      */
     @Override
     public List respondsTo(final Object obj, final String name, final Object[] argTypes) {
-        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
+        Class[] classes = castArgumentsToClassArray(argTypes);
         MetaMethod m = getMetaMethod(name, classes);
         if (m != null) {
             return Collections.singletonList(m);
@@ -322,7 +324,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
      */
     @Override
     public MetaMethod getStaticMetaMethod(final String name, final Object[] argTypes) {
-        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
+        Class[] classes = castArgumentsToClassArray(argTypes);
         return pickStaticMethod(name, classes);
     }
 
@@ -331,7 +333,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
      */
     @Override
     public MetaMethod getMetaMethod(final String name, final Object[] argTypes) {
-        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
+        Class[] classes = castArgumentsToClassArray(argTypes);
         return pickMethod(name, classes);
     }
 
@@ -926,7 +928,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         if (theClass != instanceKlazz && theClass.isAssignableFrom(instanceKlazz))
             instanceKlazz = theClass;
 
-        Class<?>[] argClasses = MetaClassHelper.castArgumentsToClassArray(arguments);
+        Class<?>[] argClasses = castArgumentsToClassArray(arguments);
 
         MetaMethod method = findMixinMethod(methodName, argClasses);
         if (method != null) {
@@ -1159,9 +1161,9 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         private MethodHandleHolder() {}
     }
 
-    private static final ClassValue<Map<String, Set<Method>>> SPECIAL_METHODS_MAP = new ClassValue<Map<String, Set<Method>>>() {
+    private static final ClassValue<Map<Method, MethodHandle>> SPECIAL_METHODS_MAP = new ClassValue<Map<Method, MethodHandle>>() {
         @Override
-        protected Map<String, Set<Method>> computeValue(Class<?> type) {
+        protected Map<Method, MethodHandle> computeValue(Class<?> type) {
             return new ConcurrentHashMap<>(4);
         }
     };
@@ -1177,16 +1179,15 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         final Class<?> receiverClass = object.getClass();
         if (isCallToSuper) {
             if (null == lookup) throw mme;
-            Class[] argTypes = MetaClassHelper.castArgumentsToClassArray(originalArguments);
-            Method superMethod = findMethod(sender, methodName, argTypes);
-            if (null == superMethod) throw mme;
-            MethodHandle superMethodHandle;
-            try {
-                superMethodHandle = lookup.unreflectSpecial(superMethod, receiverClass);
-            } catch (IllegalAccessException e) {
-                throw mme;
-            }
-            cacheMethod(sender, superMethod);
+            final MethodHandles.Lookup tmpLookup = lookup;
+            MethodHandle superMethodHandle = findMethodHandle(sender, methodName, castArgumentsToClassArray(originalArguments), superMethod -> {
+                try {
+                    return tmpLookup.unreflectSpecial(superMethod, receiverClass);
+                } catch (IllegalAccessException e) {
+                    return null;
+                }
+            });
+            if (null == superMethodHandle) throw mme;
             try {
                 return superMethodHandle.bindTo(object).invokeWithArguments(originalArguments);
             } catch (Throwable t) {
@@ -1213,16 +1214,15 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
                     throw mme;
                 }
             }
-            Class[] argTypes = MetaClassHelper.castArgumentsToClassArray(originalArguments);
-            Method thisMethod = findMethod(receiverClass, methodName, argTypes);
-            if (null == thisMethod) throw mme;
-            MethodHandle thisMethodHandle;
-            try {
-                thisMethodHandle = lookup.unreflect(thisMethod);
-            } catch (IllegalAccessException e) {
-                throw mme;
-            }
-            cacheMethod(receiverClass, thisMethod);
+            final MethodHandles.Lookup tmpLook = lookup;
+            MethodHandle thisMethodHandle = findMethodHandle(receiverClass, methodName, castArgumentsToClassArray(originalArguments), thisMethod -> {
+                try {
+                    return tmpLook.unreflect(thisMethod);
+                } catch (IllegalAccessException e) {
+                    return null;
+                }
+            });
+            if (null == thisMethodHandle) throw mme;
             try {
                 return thisMethodHandle.bindTo(object).invokeWithArguments(originalArguments);
             } catch (Throwable t) {
@@ -1231,27 +1231,33 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         }
     }
 
-    private static void cacheMethod(Class clazz, Method method) {
-        SPECIAL_METHODS_MAP.get(clazz)
-                .computeIfAbsent(method.getName(), k -> Collections.newSetFromMap(new ConcurrentHashMap<>(2)))
-                .add(method);
-    }
-
-    private static Method findMethod(Class clazz, String methodName, Class[] argTypes) {
-        Set<Method> methods = SPECIAL_METHODS_MAP.get(clazz).get(methodName);
+    private static MethodHandle findMethodHandle(Class<?> clazz, String methodName, Class[] argTypes, Function<? super Method, ? extends MethodHandle> mhFunc) {
+        Map<Method, MethodHandle> methods = SPECIAL_METHODS_MAP.get(clazz);
 
-        if (null != methods) {
-            for (Method method : methods) {
-                if (parameterTypeMatches(method.getParameterTypes(), argTypes)) {
-                    return method;
-                }
+        Method foundMethod = null;
+        for (Map.Entry<Method, MethodHandle> entry : methods.entrySet()) {
+            Method method = entry.getKey();
+            if (parameterTypeMatches(method.getParameterTypes(), argTypes)) {
+                foundMethod = method;
+                break;
             }
         }
 
-        return doFindMethod(clazz, methodName, argTypes);
+        if (null == foundMethod) {
+            foundMethod = doFindMethod(clazz, methodName, argTypes);
+        }
+
+        if (null == foundMethod) return null;
+
+        MethodHandle methodHandle = mhFunc.apply(foundMethod);
+        if (null != methodHandle) {
+            methods.put(foundMethod, methodHandle);
+        }
+
+        return methodHandle;
     }
 
-    private static Method doFindMethod(Class clazz, String messageName, Class[] argTypes) {
+    private static Method doFindMethod(Class<?> clazz, String messageName, Class[] argTypes) {
         for (Class<?> c = clazz; null != c; c = c.getSuperclass()) {
             List<Method> declaredMethodList = ReflectionUtils.getDeclaredMethods(c, messageName, argTypes);
             if (!declaredMethodList.isEmpty()) {