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 2022/05/10 15:48:15 UTC
[groovy] branch danielsun/trivial-refactoring-20220510 updated: Cache `asType` methodhandles
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch danielsun/trivial-refactoring-20220510
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/danielsun/trivial-refactoring-20220510 by this push:
new c3af7bf642 Cache `asType` methodhandles
c3af7bf642 is described below
commit c3af7bf64285a9e363b3cdcbb456e1c77f8b8333
Author: Daniel Sun <su...@apache.org>
AuthorDate: Tue May 10 23:47:29 2022 +0800
Cache `asType` methodhandles
---
.../org/codehaus/groovy/vmplugin/v8/Selector.java | 56 ++++++++++++++++++----
1 file changed, 46 insertions(+), 10 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
index 71a4133f28..1112ee7d42 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
@@ -43,6 +43,7 @@ import org.codehaus.groovy.runtime.GroovyCategorySupport;
import org.codehaus.groovy.runtime.GroovyCategorySupport.CategoryMethod;
import org.codehaus.groovy.runtime.NullObject;
import org.codehaus.groovy.runtime.dgmimpl.NumberNumberMetaMethod;
+import org.codehaus.groovy.runtime.memoize.LRUCache;
import org.codehaus.groovy.runtime.metaclass.ClosureMetaClass;
import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty;
@@ -65,6 +66,7 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Objects;
import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.ARRAYLIST_CONSTRUCTOR;
import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.BEAN_CONSTRUCTOR_PROPERTY_SETTER;
@@ -158,6 +160,7 @@ public abstract class Selector {
}
private static class CastSelector extends MethodSelector {
+ private static final MethodHandle BOOLEAN_CONSTANT_MH = MethodHandles.constant(boolean.class, Boolean.FALSE);
private final Class<?> staticSourceType, staticTargetType;
public CastSelector(MutableCallSite callSite, Object[] arguments) {
@@ -259,11 +262,12 @@ public abstract class Selector {
// boolean->boolean, Boolean->boolean, boolean->Boolean are handled by the compiler
// which leaves (T)Z and (T)Boolean, where T is the static type but runtime type of T might be Boolean
- MethodHandle ifNull = IS_NULL.asType(MethodType.methodType(boolean.class, staticSourceType));
+ MethodHandle ifNull = AS_TYPE_METHODHANDLE_CACHE.getAndPut(new AsTypeMethodHandleCacheKey(IS_NULL, staticSourceType),
+ k -> k.methodHandle.asType(MethodType.methodType(boolean.class, k.paramType)));
MethodHandle thenZero;
if (primitive) { // false
- thenZero = MethodHandles.dropArguments(MethodHandles.constant(boolean.class, Boolean.FALSE), 0, staticSourceType);
+ thenZero = MethodHandles.dropArguments(BOOLEAN_CONSTANT_MH, 0, staticSourceType);
} else { // (Boolean)null
thenZero = MethodHandles.identity(staticSourceType).asType(MethodType.methodType(Boolean.class, staticSourceType));
}
@@ -378,6 +382,7 @@ public abstract class Selector {
}
private static class InitSelector extends MethodSelector {
+ private static final MethodType OBJECT_MT = MethodType.methodType(Object.class);
private boolean beanConstructor;
public InitSelector(MutableCallSite callSite, Class<?> sender, String methodName, CallType callType, boolean safeNavigation, boolean thisCall, boolean spreadCall, Object[] arguments) {
@@ -448,7 +453,7 @@ public abstract class Selector {
// to do this we first bind the values to #setBeanProperties
MethodHandle con = BEAN_CONSTRUCTOR_PROPERTY_SETTER.bindTo(mc);
// inner class case
- MethodType foldTargetType = MethodType.methodType(Object.class);
+ MethodType foldTargetType = OBJECT_MT;
if (args.length == 3) {
con = MethodHandles.dropArguments(con, 1, targetType.parameterType(1));
foldTargetType = foldTargetType.insertParameterTypes(0, targetType.parameterType(1));
@@ -732,8 +737,9 @@ public abstract class Selector {
if (currentType != null) pt = currentType.parameterArray();
for (int i = 1; i < args.length; i++) {
if (args[i] instanceof Wrapper) {
- Class<?> type = pt[i];
- handle = MethodHandles.filterArguments(handle, i, UNWRAP_METHOD.asType(MethodType.methodType(type, Wrapper.class)));
+ final MethodHandle unwrapMH = AS_TYPE_METHODHANDLE_CACHE.getAndPut(new AsTypeMethodHandleCacheKey(UNWRAP_METHOD, pt[i]),
+ k -> k.methodHandle.asType(MethodType.methodType(k.paramType, Wrapper.class)));
+ handle = MethodHandles.filterArguments(handle, i, unwrapMH);
if (LOG_ENABLED) LOG.info("added filter for Wrapper for argument at pos " + i);
}
}
@@ -860,7 +866,9 @@ public abstract class Selector {
if (handle == null || !catchException) return;
Class<?> returnType = handle.type().returnType();
if (returnType != Object.class) {
- handle = MethodHandles.catchException(handle, GroovyRuntimeException.class, UNWRAP_EXCEPTION.asType(MethodType.methodType(returnType, GroovyRuntimeException.class)));
+ final MethodHandle unwrapExceptionMH = AS_TYPE_METHODHANDLE_CACHE.getAndPut(new AsTypeMethodHandleCacheKey(UNWRAP_EXCEPTION, returnType),
+ k -> k.methodHandle.asType(MethodType.methodType(k.paramType, GroovyRuntimeException.class)));
+ handle = MethodHandles.catchException(handle, GroovyRuntimeException.class, unwrapExceptionMH);
} else {
handle = MethodHandles.catchException(handle, GroovyRuntimeException.class, UNWRAP_EXCEPTION);
}
@@ -886,11 +894,13 @@ public abstract class Selector {
GroovyObject go = (GroovyObject) receiver;
MetaClass mc = go.getMetaClass();
// drop dummy receiver
- MethodHandle test = SAME_MC.asType(MethodType.methodType(boolean.class, MetaClass.class, targetType.parameterType(0))).bindTo(mc);
+ MethodHandle test = AS_TYPE_METHODHANDLE_CACHE.getAndPut(new AsTypeMethodHandleCacheKey(SAME_MC, targetType.parameterType(0)),
+ k -> k.methodHandle.asType(MethodType.methodType(boolean.class, MetaClass.class, k.paramType))).bindTo(mc);
handle = MethodHandles.guardWithTest(test, handle, fallback);
if (LOG_ENABLED) LOG.info("added meta class equality check");
} else if (receiver instanceof Class) {
- MethodHandle test = EQUALS.asType(MethodType.methodType(boolean.class, Object.class, targetType.parameterType(0))).bindTo(receiver);
+ MethodHandle test = AS_TYPE_METHODHANDLE_CACHE.getAndPut(new AsTypeMethodHandleCacheKey(EQUALS, targetType.parameterType(0)),
+ k -> k.methodHandle.asType(MethodType.methodType(boolean.class, Object.class, k.paramType))).bindTo(receiver);
handle = MethodHandles.guardWithTest(test, handle, fallback);
if (LOG_ENABLED) LOG.info("added class equality check");
}
@@ -924,13 +934,15 @@ public abstract class Selector {
MethodHandle test;
if (arg == null) {
- test = IS_NULL.asType(MethodType.methodType(boolean.class, paramType));
+ test = AS_TYPE_METHODHANDLE_CACHE.getAndPut(new AsTypeMethodHandleCacheKey(IS_NULL, paramType),
+ k -> k.methodHandle.asType(MethodType.methodType(boolean.class, k.paramType)));
if (LOG_ENABLED) LOG.info("added null argument check at pos " + i);
} else {
Class<?> argClass = arg.getClass();
if (paramType.isPrimitive()) continue;
//if (Modifier.isFinal(argClass.getModifiers()) && TypeHelper.argumentClassIsParameterClass(argClass,pt[i])) continue;
- test = SAME_CLASS.asType(MethodType.methodType(boolean.class, Class.class, paramType)).bindTo(argClass);
+ test = AS_TYPE_METHODHANDLE_CACHE.getAndPut(new AsTypeMethodHandleCacheKey(SAME_CLASS, paramType),
+ k -> k.methodHandle.asType(MethodType.methodType(boolean.class, Class.class, k.paramType))).bindTo(argClass);
if (LOG_ENABLED) LOG.info("added same class check at pos " + i);
}
Class<?>[] drops = new Class[i];
@@ -1071,4 +1083,28 @@ public abstract class Selector {
System.arraycopy(args, 1, ar, 0, args.length - 1);
return ar;
}
+
+ private static final LRUCache<AsTypeMethodHandleCacheKey, MethodHandle> AS_TYPE_METHODHANDLE_CACHE = new LRUCache<>(256);
+ private static class AsTypeMethodHandleCacheKey {
+ private final MethodHandle methodHandle;
+ private final Class<?> paramType;
+
+ private AsTypeMethodHandleCacheKey(MethodHandle methodHandle, Class<?> paramType) {
+ this.methodHandle = methodHandle;
+ this.paramType = paramType;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AsTypeMethodHandleCacheKey)) return false;
+ AsTypeMethodHandleCacheKey that = (AsTypeMethodHandleCacheKey) o;
+ return paramType == that.paramType && methodHandle.equals(that.methodHandle);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(methodHandle, paramType);
+ }
+ }
}