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()) {