Updates the reflective visitor pattern uses in GenerateJavaAST
to cache Method instance lookups. This cuts the runtime
of GenerateJavaAST.exec() in half.
Review at http://gwt-code-reviews.appspot.com/817802
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8683 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index 7849d45..e324a30 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -237,6 +237,56 @@
private static class JavaASTGenerationVisitor {
/**
+ * Used to cache {@link Method} lookups.
+ */
+ private static class MethodKey {
+ private Class<? extends Object> childClass;
+ private String name;
+
+ public MethodKey(String name, Class<? extends Object>childClass) {
+ this.name = name;
+ this.childClass = childClass;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof MethodKey) {
+ MethodKey otherKey = (MethodKey) obj;
+ return name.equals(otherKey.name) && childClass.equals(otherKey.childClass);
+ }
+ return super.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode() + (101 * childClass.hashCode());
+ }
+ }
+
+ /**
+ * Used to cache {@link Method} lookups.
+ */
+ private static class MethodValue {
+ private final NoSuchMethodException ex;
+ private final Method method;
+ public MethodValue(Method method) {
+ this.method = method;
+ this.ex = null;
+ }
+
+ public MethodValue(NoSuchMethodException ex) {
+ this.ex = ex;
+ this.method = null;
+ }
+
+ public Method getMethod() throws NoSuchMethodException {
+ if (this.ex != null) {
+ throw (ex);
+ }
+ return method;
+ }
+ }
+
+ /**
* The literal for the JLS identifier that represents the length
* field on an array.
*/
@@ -285,6 +335,8 @@
private final Map<JMethod, Map<String, JLabel>> labelMap = new IdentityHashMap<JMethod, Map<String, JLabel>>();
+ private final Map<MethodKey, MethodValue> methodCache = new HashMap<MethodKey, MethodValue>();
+
private final JProgram program;
private final TypeMap typeMap;
@@ -536,8 +588,7 @@
}
try {
- // TODO: This is really slow! Cache or otherwise fix.
- Method method = getClass().getDeclaredMethod(name, child.getClass());
+ Method method = getCachedMethod(name, child.getClass());
return (JNode) method.invoke(this, child);
} catch (Throwable e) {
if (e instanceof InvocationTargetException) {
@@ -2275,6 +2326,22 @@
return typeBinding;
}
+ private Method getCachedMethod(String name, Class<? extends Object> childClass) throws NoSuchMethodException {
+ MethodKey key = new MethodKey(name, childClass);
+ MethodValue value = methodCache.get(key);
+ if (value == null) {
+ try {
+ Method method = getClass().getDeclaredMethod(name, childClass);
+ value = new MethodValue(method);
+ } catch (NoSuchMethodException ex) {
+ value = new MethodValue(ex);
+ }
+ methodCache.put(key, value);
+ }
+ // Might throw an exception here.
+ return value.getMethod();
+ }
+
private JInterfaceType getOrCreateExternalType(SourceInfo info,
char[][] compoundName) {
String name = BuildTypeMap.dotify(compoundName);