Skip to content

Commit

Permalink
replacing the custom hashmap implementation in MetaMethodIndex with n…
Browse files Browse the repository at this point in the history
…ormal hashmaps
  • Loading branch information
blackdrag authored and daniellansun committed Feb 21, 2024
1 parent cab8bab commit af41551
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 386 deletions.
131 changes: 62 additions & 69 deletions src/main/java/groovy/lang/MetaClassImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,36 @@
*/
package groovy.lang;

import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiConsumer;
import org.apache.groovy.internal.util.UncheckedThrow;
import org.apache.groovy.util.BeanUtils;
import org.apache.groovy.util.SystemUtil;
Expand Down Expand Up @@ -82,37 +112,6 @@
import org.codehaus.groovy.vmplugin.VMPluginFactory;
import org.objectweb.asm.Opcodes;

import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiConsumer;

import static groovy.lang.Tuple.tuple;
import static java.lang.Character.isUpperCase;
import static org.apache.groovy.util.Arrays.concat;
Expand Down Expand Up @@ -177,7 +176,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
private MetaMethod propertyMissingGet;
private MetaMethod propertyMissingSet;
private MetaMethod methodMissing;
private MetaMethodIndex.Header mainClassMethodHeader;
private Map<String, MetaMethodIndex.Cache> mainClassMethodHeader;
private boolean permissivePropertyAccess = PERMISSIVE_PROPERTY_ACCESS;

/**
Expand Down Expand Up @@ -372,7 +371,7 @@ private void fillMethodIndex() {
}

private void populateMethods(final List<CachedClass> superClasses, final CachedClass firstGroovySuper) {
MetaMethodIndex.Header header = metaMethodIndex.getHeader(firstGroovySuper.getTheClass());
var header = metaMethodIndex.getHeader(firstGroovySuper.getTheClass());
CachedClass c;
Iterator<CachedClass> iter = superClasses.iterator();
while (iter.hasNext()) {
Expand All @@ -396,7 +395,7 @@ private void populateMethods(final List<CachedClass> superClasses, final CachedC
break;
}

MetaMethodIndex.Header last = header;
var last = header;
while (iter.hasNext()) {
c = iter.next();
header = metaMethodIndex.getHeader(c.getTheClass());
Expand Down Expand Up @@ -452,7 +451,7 @@ public boolean skipClass(final Class<?> clazz) {
}

@Override
public void methodNameAction(final Class<?> clazz, final MetaMethodIndex.Entry e) {
public void methodNameAction(final Class<?> clazz, final MetaMethodIndex.Cache e) {
if (e.methods == null)
return;

Expand Down Expand Up @@ -499,7 +498,7 @@ class MOPIter extends MethodIndexAction {
boolean useThis;

@Override
public void methodNameAction(final Class<?> c, final MetaMethodIndex.Entry e) {
public void methodNameAction(final Class<?> c, final MetaMethodIndex.Cache e) {
Object arrayOrMethod = (useThis ? e.methods : e.methodsForSuper);
if (arrayOrMethod instanceof FastArray) {
FastArray methods = (FastArray) arrayOrMethod;
Expand Down Expand Up @@ -618,11 +617,11 @@ private void inheritInterfaceNewMetaMethods(final Set<CachedClass> interfaces) {
}

private void connectMultimethods(final List<CachedClass> superClasses, final CachedClass firstGroovyClass) {
MetaMethodIndex.Header last = null;
Map<String, MetaMethodIndex.Cache> last = null;
for (ListIterator<CachedClass> iter = superClasses.listIterator(superClasses.size()); iter.hasPrevious(); ) {
CachedClass c = iter.previous();

MetaMethodIndex.Header methodIndex = metaMethodIndex.getHeader(c.getTheClass());
var methodIndex = metaMethodIndex.getHeader(c.getTheClass());
// We don't copy DGM methods to superclasses' indexes
// The reason we can do that is particular set of DGM methods in use,
// if at some point we will define DGM method for some Groovy class or
Expand Down Expand Up @@ -673,7 +672,7 @@ private CachedClass calcFirstGroovySuperClass(final List<CachedClass> superClass
private Object getMethods(final Class<?> sender, final String name, final boolean isCallToSuper) {
Object answer;

final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
final MetaMethodIndex.Cache entry = metaMethodIndex.getMethods(sender, name);
if (entry == null) {
answer = FastArray.EMPTY_LIST;
} else if (isCallToSuper) {
Expand Down Expand Up @@ -711,7 +710,7 @@ private Object getMethods(final Class<?> sender, final String name, final boolea
* @return static methods available from this class for given name
*/
private Object getStaticMethods(final Class<?> sender, final String name) {
final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
final MetaMethodIndex.Cache entry = metaMethodIndex.getMethods(sender, name);
if (entry == null)
return FastArray.EMPTY_LIST;
Object answer = entry.staticMethods;
Expand Down Expand Up @@ -743,7 +742,7 @@ public void addNewInstanceMethod(final Method method) {
addNewInstanceMethodToIndex(newMethod, metaMethodIndex.getHeader(newMethod.getDeclaringClass().getTheClass()));
}

private void addNewInstanceMethodToIndex(final MetaMethod newMethod, final MetaMethodIndex.Header header) {
private void addNewInstanceMethodToIndex(final MetaMethod newMethod, final Map<String, MetaMethodIndex.Cache> header) {
if (!newGroovyMethodsSet.contains(newMethod)) {
newGroovyMethodsSet.add(newMethod);
addMetaMethodToIndex(newMethod, header);
Expand All @@ -762,7 +761,7 @@ public void addNewStaticMethod(final Method method) {
addNewStaticMethodToIndex(newMethod, metaMethodIndex.getHeader(newMethod.getDeclaringClass().getTheClass()));
}

private void addNewStaticMethodToIndex(final MetaMethod newMethod, final MetaMethodIndex.Header header) {
private void addNewStaticMethodToIndex(final MetaMethod newMethod, final Map<String,MetaMethodIndex.Cache> header) {
if (!newGroovyMethodsSet.contains(newMethod)) {
newGroovyMethodsSet.add(newMethod);
addMetaMethodToIndex(newMethod, header);
Expand Down Expand Up @@ -1362,25 +1361,25 @@ private MetaMethod getMethodWithCachingInternal(final Class sender, final CallSi
if (GroovyCategorySupport.hasCategoryInCurrentThread())
return getMethodWithoutCaching(sender, site.getName(), params, false);

MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, site.getName());
MetaMethodIndex.Cache e = metaMethodIndex.getMethods(sender, site.getName());
if (e == null || e.methods == null)
return null;

MetaMethodIndex.CacheEntry cacheEntry = e.cachedMethod;
MetaMethodIndex.MetaMethodCache cacheEntry = e.cachedMethod;
if (cacheEntry != null && (sameClasses(cacheEntry.params, params))) {
return cacheEntry.method;
}

cacheEntry = e.cachedMethod = new MetaMethodIndex.CacheEntry(params, (MetaMethod) chooseMethod(e.name, e.methods, params));
cacheEntry = e.cachedMethod = new MetaMethodIndex.MetaMethodCache(params, (MetaMethod) chooseMethod(e.name, e.methods, params));

return cacheEntry.method;
}

private MetaMethod getSuperMethodWithCaching(final Object[] arguments, final MetaMethodIndex.Entry e) {
private MetaMethod getSuperMethodWithCaching(final Object[] arguments, final MetaMethodIndex.Cache e) {
if (e.methodsForSuper == null)
return null;

MetaMethodIndex.CacheEntry cacheEntry = e.cachedMethodForSuper;
MetaMethodIndex.MetaMethodCache cacheEntry = e.cachedMethodForSuper;

if (cacheEntry != null && cacheEntry.method != null
&& MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.methodsForSuper instanceof MetaMethod)) {
Expand All @@ -1389,16 +1388,16 @@ private MetaMethod getSuperMethodWithCaching(final Object[] arguments, final Met

Class<?>[] types = MetaClassHelper.convertToTypeArray(arguments);
MetaMethod method = (MetaMethod) chooseMethod(e.name, e.methodsForSuper, types);
cacheEntry = e.cachedMethodForSuper = new MetaMethodIndex.CacheEntry(types, method.isAbstract() ? null : method);
cacheEntry = e.cachedMethodForSuper = new MetaMethodIndex.MetaMethodCache(types, method.isAbstract() ? null : method);

return cacheEntry.method;
}

private MetaMethod getNormalMethodWithCaching(final Object[] arguments, final MetaMethodIndex.Entry e) {
private MetaMethod getNormalMethodWithCaching(final Object[] arguments, final MetaMethodIndex.Cache e) {
if (e.methods == null)
return null;

MetaMethodIndex.CacheEntry cacheEntry = e.cachedMethod;
MetaMethodIndex.MetaMethodCache cacheEntry = e.cachedMethod;

if (cacheEntry != null && cacheEntry.method != null
&& MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.methods instanceof MetaMethod)) {
Expand All @@ -1407,7 +1406,7 @@ private MetaMethod getNormalMethodWithCaching(final Object[] arguments, final Me

Class<?>[] types = MetaClassHelper.convertToTypeArray(arguments);
MetaMethod method = (MetaMethod) chooseMethod(e.name, e.methods, types);
cacheEntry = e.cachedMethod = new MetaMethodIndex.CacheEntry(types, method);
cacheEntry = e.cachedMethod = new MetaMethodIndex.MetaMethodCache(types, method);

return cacheEntry.method;
}
Expand All @@ -1421,8 +1420,8 @@ public Constructor retrieveConstructor(Class[] arguments) {
}

public MetaMethod retrieveStaticMethod(String methodName, Object[] arguments) {
final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(theClass, methodName);
MetaMethodIndex.CacheEntry cacheEntry;
final MetaMethodIndex.Cache e = metaMethodIndex.getMethods(theClass, methodName);
MetaMethodIndex.MetaMethodCache cacheEntry;
if (e != null) {
cacheEntry = e.cachedStaticMethod;

Expand All @@ -1432,7 +1431,7 @@ public MetaMethod retrieveStaticMethod(String methodName, Object[] arguments) {
}

final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
cacheEntry = new MetaMethodIndex.CacheEntry(classes, pickStaticMethod(methodName, classes));
cacheEntry = new MetaMethodIndex.MetaMethodCache(classes, pickStaticMethod(methodName, classes));

e.cachedStaticMethod = cacheEntry;

Expand Down Expand Up @@ -2485,8 +2484,8 @@ private void applyStrayPropertyMethods(Iterable<CachedClass> classes, Map<Cached
* Looks for any stray getters/setters that may be used to define a property.
*/
private void applyStrayPropertyMethods(CachedClass source, Map<String, MetaProperty> target, boolean isThis) {
MetaMethodIndex.Header header = metaMethodIndex.getHeader(source.getTheClass());
for (MetaMethodIndex.Entry e = header.head; e != null; e = e.nextClassEntry) {
var header = metaMethodIndex.getHeader(source.getTheClass());
for (MetaMethodIndex.Cache e : header.values()) {
String methodName = e.name;
int methodNameLength = methodName.length();
boolean isBooleanGetter = methodName.startsWith("is");
Expand Down Expand Up @@ -3026,15 +3025,9 @@ public void addMetaMethod(MetaMethod method) {
addMetaMethodToIndex(method, metaMethodIndex.getHeader(declaringClass.getTheClass()));
}

protected void addMetaMethodToIndex(MetaMethod method, MetaMethodIndex.Header header) {
protected void addMetaMethodToIndex(MetaMethod method, Map<String, MetaMethodIndex.Cache> cacheIndex) {
checkIfStdMethod(method);

String name = method.getName();
MetaMethodIndex.Entry e = metaMethodIndex.getOrPutMethods(name, header);
if (method.isStatic()) {
e.staticMethods = metaMethodIndex.addMethodToList(e.staticMethods, method);
}
e.methods = metaMethodIndex.addMethodToList(e.methods, method);
metaMethodIndex.addMetaMethod(method, cacheIndex);
}

/**
Expand Down Expand Up @@ -3751,17 +3744,17 @@ protected Object getSubclassMetaMethods(String methodName) {

private abstract class MethodIndexAction {
public void iterate() {
for (Map.Entry<Class, MetaMethodIndex.Header> classEntry : metaMethodIndex.methodHeaders.entrySet()) {
Class clazz = classEntry.getKey();
for (Map.Entry<Class<?>, Map<String, MetaMethodIndex.Cache>> classEntry : metaMethodIndex.indexMap.entrySet()) {
Class<?> clazz = classEntry.getKey();
if (skipClass(clazz)) continue;
MetaMethodIndex.Header header = classEntry.getValue();
for (MetaMethodIndex.Entry nameEntry = header.head; nameEntry != null; nameEntry = nameEntry.nextClassEntry) {
var header = classEntry.getValue();
for (MetaMethodIndex.Cache nameEntry : header.values()) {
methodNameAction(clazz, nameEntry);
}
}
}

public abstract void methodNameAction(Class<?> clazz, MetaMethodIndex.Entry methods);
public abstract void methodNameAction(Class<?> clazz, MetaMethodIndex.Cache methods);

public boolean skipClass(final Class<?> clazz) {
return false;
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/groovy/lang/MetaMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ public MetaMethod(Class [] pt) {
*
* @param arguments the arguments to check
* @throws IllegalArgumentException if the parameters are not valid
* @deprecated
*/
@Deprecated
public void checkParameters(Class[] arguments) {
// let's check that the argument types are valid
if (!isValidMethod(arguments)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public ParameterTypes(Class[] pt) {
nativeParamTypes = pt;
}

/**
* @deprecated
*/
@Deprecated
public ParameterTypes(String[] pt) {
nativeParamTypes = new Class[pt.length];
for (int i = 0; i != pt.length; ++i) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,12 @@ private synchronized void initAttributes() {
public synchronized void initialize() {
if (!isInitialized()) {
CachedMethod[] methodArray = theCachedClass.getMethods();
synchronized (theCachedClass) {
for (final CachedMethod cachedMethod : methodArray) {
if (!cachedMethod.getName().equals(CLOSURE_DO_CALL_METHOD)) continue;
closureMethods.add(cachedMethod);
}
for (final CachedMethod cachedMethod : methodArray) {
if (!cachedMethod.getName().equals(CLOSURE_DO_CALL_METHOD)) continue;
closureMethods.add(cachedMethod);
}
assignMethodChooser();
setInitialized(true);
super.reinitialize();
}
}

Expand Down Expand Up @@ -664,7 +662,7 @@ public List respondsTo(final Object obj, final String name) {
}

private synchronized void loadMetaInfo() {
if (metaMethodIndex.isEmpty()) {
if (!isInitialized()) {
reinitialize();
}
}
Expand Down
Loading

0 comments on commit af41551

Please sign in to comment.