less memory occupied by dom (IDEA-89273)

This commit is contained in:
peter
2012-07-26 18:15:06 +02:00
parent bce8590921
commit 36e846fe99
5 changed files with 81 additions and 81 deletions
@@ -34,6 +34,7 @@ public abstract class DomGenericInfoEx implements DomGenericInfo {
public abstract boolean checkInitialized();
@Nullable
public abstract Invocation createInvocation(final JavaMethod method);
@NotNull
@@ -21,8 +21,6 @@ import com.intellij.semantic.SemElement;
import com.intellij.semantic.SemKey;
import com.intellij.semantic.SemService;
import com.intellij.util.*;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.xml.*;
import com.intellij.util.xml.events.DomEvent;
import com.intellij.util.xml.reflect.*;
@@ -49,8 +47,8 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
private static final Logger LOG = Logger.getInstance("#com.intellij.util.xml.impl.DomInvocationHandler");
public static final Method ACCEPT_METHOD = ReflectionUtil.getMethod(DomElement.class, "accept", DomElementVisitor.class);
public static final Method ACCEPT_CHILDREN_METHOD = ReflectionUtil.getMethod(DomElement.class, "acceptChildren", DomElementVisitor.class);
private static final JavaMethod ourGetValue = JavaMethod.getMethod(GenericValue.class, new JavaMethodSignature("getValue"));
private final Type myAbstractType;
private final Type myType;
private final DomManagerImpl myManager;
private final EvaluatedXmlName myTagName;
@@ -61,45 +59,8 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
private final DomElement myProxy;
private DomGenericInfoEx myGenericInfo;
private final InvocationCache myInvocationCache;
private final FactoryMap<JavaMethod, Converter> myScalarConverters = new FactoryMap<JavaMethod, Converter>() {
protected Converter create(final JavaMethod method) {
final Type returnType = method.getGenericReturnType();
final Type type = returnType == void.class ? method.getGenericParameterTypes()[0] : returnType;
final Class parameter = ReflectionUtil.substituteGenericType(type, myType);
LOG.assertTrue(parameter != null, type + " " + myType);
Converter converter = getConverter(new AnnotatedElement() {
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
return myInvocationCache.getMethodAnnotation(method, annotationClass);
}
}, parameter);
if (converter == null && type instanceof TypeVariable) {
converter = getConverter(DomInvocationHandler.this, DomUtil.getGenericValueParameter(myType));
}
if (converter == null) {
converter = myManager.getConverterManager().getConverterByClass(parameter);
}
if (converter == null) {
throw new AssertionError("No converter specified: String<->" + parameter.getName() + "; method=" + method + "; place=" + myChildDescription);
}
return converter;
}
};
private final FactoryMap<Method, Invocation> myAccessorInvocations = new ConcurrentFactoryMap<Method, Invocation>() {
@Override
protected Invocation create(Method signature) {
final JavaMethod method = JavaMethod.getMethod(getRawType(), signature);
if (myInvocationCache.isTagValueGetter(method)) {
return new GetInvocation(getScalarConverter(method));
}
if (myInvocationCache.isTagValueSetter(method)) {
return new SetInvocation(getScalarConverter(method));
}
return null;
}
};
private volatile Converter myScalarConverter = null;
private volatile SmartFMap<Method, Invocation> myAccessorInvocations = SmartFMap.emptyMap();
protected DomInvocationHandler(Type type, DomParentStrategy parentStrategy,
final EvaluatedXmlName tagName,
@@ -110,7 +71,6 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
myParentStrategy = parentStrategy;
myTagName = tagName;
myChildDescription = childDescription;
myAbstractType = type;
myLastModCount = manager.getPsiModificationCount();
myType = narrowType(type);
@@ -153,10 +113,6 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
return myType;
}
final Type getAbstractType() {
return myAbstractType;
}
@Nullable
protected String getValue() {
final XmlTag tag = getXmlTag();
@@ -441,12 +397,36 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
}
@NotNull
protected final Converter getScalarConverter(final JavaMethod method) {
final Converter converter;
synchronized (myScalarConverters) {
converter = myScalarConverters.get(method);
protected final Converter getScalarConverter() {
Converter converter = myScalarConverter;
if (converter == null) {
converter = myScalarConverter = createConverter(ourGetValue);
}
return converter;
}
@NotNull
private Converter createConverter(final JavaMethod method) {
Converter converter;
final Type returnType = method.getGenericReturnType();
final Type type = returnType == void.class ? method.getGenericParameterTypes()[0] : returnType;
final Class parameter = ReflectionUtil.substituteGenericType(type, myType);
LOG.assertTrue(parameter != null, type + " " + myType);
converter = getConverter(new AnnotatedElement() {
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
return myInvocationCache.getMethodAnnotation(method, annotationClass);
}
}, parameter);
if (converter == null && type instanceof TypeVariable) {
converter = getConverter(DomInvocationHandler.this, DomUtil.getGenericValueParameter(myType));
}
if (converter == null) {
converter = myManager.getConverterManager().getConverterByClass(parameter);
}
if (converter == null) {
throw new AssertionError("No converter specified: String<->" + parameter.getName() + "; method=" + method + "; place=" + myChildDescription);
}
assert converter != null;
return converter;
}
@@ -546,7 +526,7 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
}
private static <T extends DomElement> T _getParentOfType(Class<T> requiredClass, DomElement element) {
while (element != null && !(requiredClass.isInstance(element))) {
while (element != null && !requiredClass.isInstance(element)) {
element = element.getParent();
}
return (T)element;
@@ -609,24 +589,39 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
@Nullable
public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return doInvoke(method, args);
return findInvocation(method).invoke(this, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
@Nullable
private Object doInvoke(final Method method, final Object... args) throws Throwable {
Invocation invocation = myInvocationCache.getInvocation(method);
if (invocation == null) {
invocation = myAccessorInvocations.get(method);
if (invocation == null) {
invocation = myGenericInfo.createInvocation(JavaMethod.getMethod(getRawType(), method));
myInvocationCache.putInvocation(method, invocation);
}
@NotNull
private Invocation findInvocation(Method method) {
Invocation invocation = myAccessorInvocations.get(method);
if (invocation != null) return invocation;
invocation = myInvocationCache.getInvocation(method);
if (invocation != null) return invocation;
JavaMethod javaMethod = JavaMethod.getMethod(getRawType(), method);
invocation = myGenericInfo.createInvocation(javaMethod);
if (invocation != null) {
myInvocationCache.putInvocation(method, invocation);
return invocation;
}
return invocation.invoke(this, args);
if (myInvocationCache.isTagValueGetter(javaMethod)) {
invocation = new GetInvocation(createConverter(javaMethod));
}
else if (myInvocationCache.isTagValueSetter(javaMethod)) {
invocation = new SetInvocation(createConverter(javaMethod));
}
else {
throw new RuntimeException("No implementation for method " + method.toString() + " in class " + myType);
}
myAccessorInvocations = myAccessorInvocations.plus(method, invocation);
return invocation;
}
private static void setTagValue(final XmlTag tag, final String value) {
@@ -105,11 +105,10 @@ public class InvocationCache {
return attribute != null ? attribute.getValueElement() : null;
}
});
final JavaMethod getValue = JavaMethod.getMethod(GenericValue.class, new JavaMethodSignature("getValue"));
ourCoreInvocations.put(new JavaMethodSignature("getConverter"), new Invocation() {
public final Object invoke(final DomInvocationHandler<?> handler, final Object[] args) throws Throwable {
try {
return handler.getScalarConverter(getValue);
return handler.getScalarConverter();
}
catch (Throwable e) {
final Throwable cause = e.getCause();
@@ -150,7 +150,7 @@ public class StaticGenericInfo extends DomGenericInfoEx {
return new AddChildInvocation(getTypeGetter(method), getIndexGetter(method), description, description.getType());
}
throw new RuntimeException("No implementation for method " + method.toString() + " in class " + myClass);
return null;
}
private static Function<Object[], Type> getTypeGetter(final JavaMethod method) {
@@ -15,9 +15,9 @@
*/
package com.intellij.util.xml;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.SmartFMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@@ -33,17 +33,7 @@ public final class JavaMethod implements AnnotatedElement{
private final JavaMethodSignature mySignature;
private final Class myDeclaringClass;
private final Method myMethod;
private final FactoryMap<Class, Annotation> myAnnotationsMap = new ConcurrentFactoryMap<Class, Annotation>() {
protected Annotation create(Class annotationClass) {
for (Method method : mySignature.getAllMethods(myDeclaringClass)) {
final Annotation annotation = method.getAnnotation(annotationClass);
if (annotation != null) {
return annotation;
}
}
return null;
}
};
private volatile SmartFMap<Class, Annotation> myAnnotationsMap = SmartFMap.emptyMap();
private JavaMethod(final Class declaringClass, final JavaMethodSignature signature) {
mySignature = signature;
@@ -102,7 +92,22 @@ public final class JavaMethod implements AnnotatedElement{
}
public final <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
return (T)myAnnotationsMap.get(annotationClass);
//noinspection unchecked
T annotation = (T)myAnnotationsMap.get(annotationClass);
if (annotation == null) {
myAnnotationsMap = myAnnotationsMap.plus(annotationClass, annotation = findAnnotation(annotationClass));
}
return annotation;
}
@Nullable private <T extends Annotation> T findAnnotation(Class<T> annotationClass) {
for (Method method : mySignature.getAllMethods(myDeclaringClass)) {
final T annotation = method.getAnnotation(annotationClass);
if (annotation != null) {
return annotation;
}
}
return null;
}
@Override