Author: [email protected]
Date: Wed Apr 1 12:13:09 2009
New Revision: 5151
Modified:
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/AbstractMembers.java
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/DelegateMembers.java
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/Members.java
Log:
Refactor of TypeOracle's AbstractMembers, Members, DelegatingMembers to use
less memory.
DelegatingMembers is now completely lazy, and we avoid the extremely
expensive LinkedHashMap.
Review by: jat
Modified:
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/AbstractMembers.java
==============================================================================
---
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/AbstractMembers.java
(original)
+++
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/AbstractMembers.java
Wed Apr 1 12:13:09 2009
@@ -15,9 +15,7 @@
*/
package com.google.gwt.core.ext.typeinfo;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@@ -26,7 +24,6 @@
protected final JClassType classType;
private JMethod[] cachedOverridableMethods;
- private final Map<String, JClassType> nestedTypes = new HashMap<String,
JClassType>();
public AbstractMembers(JClassType classType) {
this.classType = classType;
@@ -43,9 +40,7 @@
return null;
}
- public JField findField(String name) {
- return doGetFields().get(name);
- }
+ public abstract JField findField(String name);
public JMethod findMethod(String name, JType[] paramTypes) {
JMethod[] overloads = getOverloads(name);
@@ -82,9 +77,7 @@
return field;
}
- public JField[] getFields() {
- return doGetFields().values().toArray(TypeOracle.NO_JFIELDS);
- }
+ public abstract JField[] getFields();
public JMethod getMethod(String name, JType[] paramTypes)
throws NotFoundException {
@@ -95,13 +88,7 @@
return result;
}
- public JMethod[] getMethods() {
- List<JMethod> resultMethods = new ArrayList<JMethod>();
- for (List<JMethod> overloads : doGetMethods().values()) {
- resultMethods.addAll(overloads);
- }
- return resultMethods.toArray(TypeOracle.NO_JMETHODS);
- }
+ public abstract JMethod[] getMethods();
public JClassType getNestedType(String typeName) throws
NotFoundException {
JClassType result = findNestedType(typeName);
@@ -112,17 +99,10 @@
}
public JClassType[] getNestedTypes() {
- return nestedTypes.values().toArray(TypeOracle.NO_JCLASSES);
+ return doGetNestedTypes().values().toArray(TypeOracle.NO_JCLASSES);
}
- public JMethod[] getOverloads(String name) {
- List<?> resultMethods = doGetMethods().get(name);
- if (resultMethods != null) {
- return resultMethods.toArray(TypeOracle.NO_JMETHODS);
- } else {
- return TypeOracle.NO_JMETHODS;
- }
- }
+ public abstract JMethod[] getOverloads(String name);
public JMethod[] getOverridableMethods() {
if (cachedOverridableMethods == null) {
@@ -132,45 +112,28 @@
getOverridableMethodsOnSuperclassesAndThisClass(methodsBySignature);
}
int size = methodsBySignature.size();
- Collection<JMethod> leafMethods = methodsBySignature.values();
- cachedOverridableMethods = leafMethods.toArray(new JMethod[size]);
+ if (size == 0) {
+ cachedOverridableMethods = TypeOracle.NO_JMETHODS;
+ } else {
+ Collection<JMethod> leafMethods = methodsBySignature.values();
+ cachedOverridableMethods = leafMethods.toArray(new JMethod[size]);
+ }
}
return cachedOverridableMethods;
}
- protected void addConstructor(JConstructor ctor) {
- assert (!doGetConstructors().contains(ctor));
- doGetConstructors().add(ctor);
- }
+ protected abstract void addConstructor(JConstructor ctor);
- protected void addField(JField field) {
- Object existing = doGetFields().put(field.getName(), field);
- assert (existing == null);
- }
+ protected abstract void addField(JField field);
- protected void addMethod(JMethod method) {
- String methodName = method.getName();
- Map<String, List<JMethod>> methods = doGetMethods();
- List<JMethod> overloads = methods.get(methodName);
- if (overloads == null) {
- overloads = new ArrayList<JMethod>();
- methods.put(methodName, overloads);
- }
- overloads.add(method);
- }
-
- protected void addNestedType(JClassType type) {
- nestedTypes.put(type.getSimpleSourceName(), type);
- }
+ protected abstract void addMethod(JMethod method);
protected abstract List<JConstructor> doGetConstructors();
- protected abstract Map<String, JField> doGetFields();
-
- protected abstract Map<String, List<JMethod>> doGetMethods();
+ protected abstract Map<String, JClassType> doGetNestedTypes();
protected JClassType findNestedTypeImpl(String[] typeName, int index) {
- JClassType found = nestedTypes.get(typeName[index]);
+ JClassType found = doGetNestedTypes().get(typeName[index]);
if (found == null) {
return null;
} else if (index < typeName.length - 1) {
Modified:
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/DelegateMembers.java
==============================================================================
---
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/DelegateMembers.java
(original)
+++
trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/DelegateMembers.java
Wed Apr 1 12:13:09 2009
@@ -15,8 +15,11 @@
*/
package com.google.gwt.core.ext.typeinfo;
+import com.google.gwt.dev.util.collect.HashMap;
+import com.google.gwt.dev.util.collect.Lists;
+import com.google.gwt.dev.util.collect.Maps;
+
import java.util.ArrayList;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -25,10 +28,19 @@
* {...@link JDelegatingClassType} from its corresponding base type on demand.
*/
class DelegateMembers extends AbstractMembers {
+ /**
+ * Implementation note: it is critical that everything in this class is
+ * computed as lazily as possible. Many, many more parameterized types,
raw
+ * types, type bindings, or wilcard types can be created than real
classes,
+ * and computing anything up front would add runtime overhead and memory.
+ */
+
private final JClassType baseType;
+ private Map<String, JField> fieldMap;
+ private JField[] fields;
private List<JConstructor> lazyConstructors;
- private Map<String, JField> lazyFields;
- private Map<String, List<JMethod>> lazyMethods;
+ private Map<String, Object> methodMap;
+ private JMethod[] methods;
private final Substitution substitution;
/**
@@ -41,6 +53,53 @@
}
@Override
+ public JField findField(String name) {
+ initFields();
+ return fieldMap.get(name);
+ }
+
+ @Override
+ public JField[] getFields() {
+ initFields();
+ return fields.length == 0 ? fields : fields.clone();
+ }
+
+ @Override
+ public JMethod[] getMethods() {
+ initMethods();
+ return methods.length == 0 ? methods : methods.clone();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public JMethod[] getOverloads(String name) {
+ initMethods();
+ Object object = methodMap.get(name);
+ if (object == null) {
+ return TypeOracle.NO_JMETHODS;
+ } else if (object instanceof JMethod) {
+ return new JMethod[] {(JMethod) object};
+ } else {
+ return ((JMethod[]) object).clone();
+ }
+ }
+
+ @Override
+ protected void addConstructor(JConstructor ctor) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void addField(JField field) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void addMethod(JMethod method) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
protected List<JConstructor> doGetConstructors() {
if (lazyConstructors != null) {
/*
@@ -55,52 +114,33 @@
for (JConstructor baseCtor : baseCtors) {
JConstructor newCtor = new JConstructor(getParentType(), baseCtor);
initializeParams(baseCtor, newCtor);
- addConstructor(newCtor);
+ lazyConstructors.add(newCtor);
}
- return lazyConstructors;
+ return lazyConstructors = Lists.normalize(lazyConstructors);
}
@Override
- protected Map<String, JField> doGetFields() {
- if (lazyFields != null) {
- /*
- * Return if the fields are being initialized or have been
initialized.
- */
- return lazyFields;
- }
- lazyFields = new LinkedHashMap<String, JField>();
+ protected Map<String, JClassType> doGetNestedTypes() {
+ // TODO: is this correct?
+ return Maps.create();
+ }
- JField[] baseFields = baseType.getFields();
- for (JField baseField : baseFields) {
+ private void initFields() {
+ if (fields != null) {
+ return;
+ }
+ // Transitively sorted.
+ fields = baseType.getFields();
+ fieldMap = new HashMap<String, JField>();
+ for (int i = 0; i < fields.length; ++i) {
+ JField baseField = fields[i];
JField newField = new JField(getParentType(), baseField);
newField.setType(substitution.getSubstitution(baseField.getType()));
- addField(newField);
- }
-
- return lazyFields;
- }
-
- @Override
- protected Map<String, List<JMethod>> doGetMethods() {
- if (lazyMethods != null) {
- /*
- * Return if the methods are being initialized or have been
initialized.
- */
- return lazyMethods;
- }
- lazyMethods = new LinkedHashMap<String, List<JMethod>>();
-
- JMethod[] baseMethods = baseType.getMethods();
- for (JMethod baseMethod : baseMethods) {
- JMethod newMethod = new JMethod(getParentType(), baseMethod);
- initializeParams(baseMethod, newMethod);
-
newMethod.setReturnType(substitution.getSubstitution(baseMethod.getReturnType()));
- initializeExceptions(baseMethod, newMethod);
- addMethod(newMethod);
+ fields[i] = newField;
+ fieldMap.put(newField.getName(), newField);
}
-
- return lazyMethods;
+ fieldMap = Maps.normalize(fieldMap);
}
private void initializeExceptions(JAbstractMethod srcMethod,
@@ -118,5 +158,47 @@
newParam.setType(substitution.getSubstitution(srcParam.getType()));
newMethod.addParameter(newParam);
}
+ }
+
+ @SuppressWarnings("unchecked")
+ private void initMethods() {
+ if (methods != null) {
+ return;
+ }
+ // Transitively sorted.
+ methods = baseType.getMethods();
+ methodMap = new HashMap<String, Object>();
+ for (int i = 0; i < methods.length; ++i) {
+ JMethod baseMethod = methods[i];
+ JMethod newMethod = new JMethod(getParentType(), baseMethod);
+ initializeParams(baseMethod, newMethod);
+
newMethod.setReturnType(substitution.getSubstitution(baseMethod.getReturnType()));
+ initializeExceptions(baseMethod, newMethod);
+ methods[i] = newMethod;
+
+ String methodName = newMethod.getName();
+ Object object = methodMap.get(methodName);
+ if (object == null) {
+ methodMap.put(methodName, newMethod);
+ } else if (object instanceof JMethod) {
+ List<JMethod> list = new ArrayList<JMethod>(2);
+ list.add((JMethod) object);
+ list.add(newMethod);
+ methodMap.put(methodName, list);
+ } else {
+ List<JMethod> list = (List<JMethod>) object;
+ list.add(newMethod);
+ }
+ }
+
+ // Replace the ArrayLists with plain arrays.
+ for (String methodName : methodMap.keySet()) {
+ Object object = methodMap.get(methodName);
+ if (object instanceof List) {
+ List<JMethod> list = (List<JMethod>) object;
+ methodMap.put(methodName, list.toArray(TypeOracle.NO_JMETHODS));
+ }
+ }
+ methodMap = Maps.normalize(methodMap);
}
}
Modified: trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/Members.java
==============================================================================
--- trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/Members.java
(original)
+++ trunk/dev/core/src/com/google/gwt/core/ext/typeinfo/Members.java Wed
Apr 1 12:13:09 2009
@@ -15,8 +15,10 @@
*/
package com.google.gwt.core.ext.typeinfo;
+import com.google.gwt.dev.util.collect.Lists;
+import com.google.gwt.dev.util.collect.Maps;
+
import java.util.ArrayList;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -24,26 +26,106 @@
* A container for methods and fields.
*/
class Members extends AbstractMembers {
- private final List<JConstructor> constructors = new
ArrayList<JConstructor>();
- private final Map<String, JField> fields = new LinkedHashMap<String,
JField>();
- private final Map<String, List<JMethod>> methods = new
LinkedHashMap<String, List<JMethod>>();
+ /**
+ * Implementation note: cannot be lazily computed because unlike
+ * {...@link DelegateMembers}, this serves as the real internal container
for
+ * real classes.
+ */
+
+ private List<JConstructor> constructors = Lists.create();
+ private Map<String, JField> fieldMap = Maps.create();
+ private List<JField> fields = Lists.create();
+ private Map<String, Object> methodMap = Maps.create();
+ private List<String> methodOrder = Lists.create();
+ private Map<String, JClassType> nestedTypes = Maps.create();
public Members(JClassType classType) {
super(classType);
}
@Override
+ public JField findField(String name) {
+ return fieldMap.get(name);
+ }
+
+ @Override
+ public JField[] getFields() {
+ return fields.toArray(TypeOracle.NO_JFIELDS);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public JMethod[] getMethods() {
+ List<JMethod> result = new ArrayList<JMethod>();
+ for (String methodName : methodOrder) {
+ Object object = methodMap.get(methodName);
+ if (object instanceof JMethod) {
+ result.add((JMethod) object);
+ } else {
+ result.addAll((List<JMethod>) object);
+ }
+ }
+ return result.toArray(TypeOracle.NO_JMETHODS);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public JMethod[] getOverloads(String name) {
+ Object object = methodMap.get(name);
+ if (object == null) {
+ return TypeOracle.NO_JMETHODS;
+ } else if (object instanceof JMethod) {
+ return new JMethod[] {(JMethod) object};
+ } else {
+ List<JMethod> overloads = (List<JMethod>) object;
+ return overloads.toArray(TypeOracle.NO_JMETHODS);
+ }
+ }
+
+ @Override
+ protected void addConstructor(JConstructor ctor) {
+ assert (!constructors.contains(ctor));
+ constructors = Lists.add(constructors, ctor);
+ }
+
+ @Override
+ protected void addField(JField field) {
+ assert !fieldMap.containsKey(field.getName());
+ fieldMap = Maps.put(fieldMap, field.getName(), field);
+ fields = Lists.add(fields, field);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void addMethod(JMethod method) {
+ String methodName = method.getName();
+ Object object = methodMap.get(methodName);
+ if (object == null) {
+ methodMap = Maps.put(methodMap, methodName, method);
+ methodOrder = Lists.add(methodOrder, methodName);
+ } else if (object instanceof JMethod) {
+ List<JMethod> overloads = new ArrayList<JMethod>(2);
+ overloads.add((JMethod) object);
+ overloads.add(method);
+ methodMap = Maps.put(methodMap, methodName, overloads);
+ } else {
+ List<JMethod> overloads = (List<JMethod>) object;
+ overloads.add(method);
+ }
+ }
+
+ @Override
protected List<JConstructor> doGetConstructors() {
return constructors;
}
@Override
- protected Map<String, JField> doGetFields() {
- return fields;
+ protected Map<String, JClassType> doGetNestedTypes() {
+ return nestedTypes;
}
- @Override
- protected Map<String, List<JMethod>> doGetMethods() {
- return methods;
+ void addNestedType(JClassType type) {
+ nestedTypes = Maps.put(nestedTypes, type.getSimpleSourceName(), type);
}
+
}
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---