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:16 UTC

[groovy] branch danielsun/trivial-tweak-20210626 created (now 23ca708)

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

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


      at 23ca708  Trivial tweak: avoid creating method handle repeatedly

This branch includes the following new commits:

     new 23ca708  Trivial tweak: avoid creating method handle repeatedly

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


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

Posted by su...@apache.org.
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()) {