Using new collections to reduce memory usage of CompilationState, TypeOracle, ResourceOracle.

- ResourceOracle
- CompilationState
- TypeOracle

Review by: jat

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5150 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/Annotations.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/Annotations.java
index 3b2b649..5da6638 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/Annotations.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/Annotations.java
@@ -15,10 +15,12 @@
  */
 package com.google.gwt.core.ext.typeinfo;
 
+import com.google.gwt.dev.util.collect.HashMap;
+import com.google.gwt.dev.util.collect.Maps;
+
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Inherited;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -26,10 +28,28 @@
  * Default implementation of the {@link HasAnnotations} interface.
  */
 class Annotations implements HasAnnotations {
+
+  private static Map<Class<? extends Annotation>, Annotation> copyOfAnnotations(
+      Annotations otherAnnotations) {
+    Map<Class<? extends Annotation>, Annotation> declaredAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
+    if (otherAnnotations != null) {
+      Annotation[] otherDeclaredAnnotations = otherAnnotations.getDeclaredAnnotations();
+      for (Annotation otherDeclaredAnnotation : otherDeclaredAnnotations) {
+        Class<? extends Annotation> otherDeclaredAnnotationType = otherDeclaredAnnotation.annotationType();
+        assert (otherDeclaredAnnotationType != null);
+        assert (!declaredAnnotations.containsKey(otherDeclaredAnnotationType));
+
+        declaredAnnotations.put(otherDeclaredAnnotationType,
+            otherDeclaredAnnotation);
+      }
+    }
+    return declaredAnnotations;
+  }
+
   /**
    * All annotations declared on the annotated element.
    */
-  private final Map<Class<? extends Annotation>, Annotation> declaredAnnotations = new HashMap<Class<? extends Annotation>, Annotation>();
+  private Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
 
   /**
    * Lazily initialized collection of annotations declared on or inherited by
@@ -43,27 +63,22 @@
   private Annotations parent;
 
   Annotations() {
+    this.declaredAnnotations = Maps.create();
   }
-  
+
   Annotations(Annotations otherAnnotations) {
-    if (otherAnnotations != null) {
-      Annotation[] otherDeclaredAnnotations = otherAnnotations.getDeclaredAnnotations();
-      for (Annotation otherDeclaredAnnotation : otherDeclaredAnnotations) {
-        addAnnotation(otherDeclaredAnnotation.annotationType(),
-            otherDeclaredAnnotation);
-      }
-    }
+    this(copyOfAnnotations(otherAnnotations));
   }
 
   Annotations(Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
-    this.declaredAnnotations.putAll(declaredAnnotations);
+    this.declaredAnnotations = Maps.normalize(declaredAnnotations);
   }
 
   public void addAnnotations(
       Map<Class<? extends Annotation>, Annotation> annotations) {
     if (annotations != null) {
       assert (!annotations.containsValue(null));
-      declaredAnnotations.putAll(annotations);
+      declaredAnnotations = Maps.putAll(declaredAnnotations, annotations);
     }
   }
 
@@ -87,15 +102,6 @@
     return getAnnotation(annotationClass) != null;
   }
 
-  void addAnnotation(Class<? extends Annotation> annotationClass,
-      Annotation annotationInstance) {
-    assert (annotationClass != null);
-    assert (annotationInstance != null);
-    assert (!declaredAnnotations.containsKey(annotationClass));
-
-    declaredAnnotations.put(annotationClass, annotationInstance);
-  }
-
   void setParent(Annotations parent) {
     this.parent = parent;
   }
@@ -116,6 +122,7 @@
       }
 
       lazyAnnotations.putAll(declaredAnnotations);
+      lazyAnnotations = Maps.normalize(lazyAnnotations);
     } else {
       lazyAnnotations = declaredAnnotations;
     }
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JAbstractMethod.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JAbstractMethod.java
index aa54e64..925ddb6 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JAbstractMethod.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JAbstractMethod.java
@@ -15,8 +15,9 @@
  */
 package com.google.gwt.core.ext.typeinfo;
 
+import com.google.gwt.dev.util.collect.Lists;
+
 import java.lang.annotation.Annotation;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -36,11 +37,11 @@
 
   private final String name;
 
-  private final List<JParameter> params = new ArrayList<JParameter>();
+  private List<JParameter> params = Lists.create();
 
-  private final List<JType> thrownTypes = new ArrayList<JType>();
+  private List<JType> thrownTypes = Lists.create();
 
-  private final List<JTypeParameter> typeParams = new ArrayList<JTypeParameter>();
+  private List<JTypeParameter> typeParams = Lists.create();
 
   JAbstractMethod(JAbstractMethod srcMethod) {
     this.annotations = new Annotations(srcMethod.annotations);
@@ -55,13 +56,10 @@
       Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
       JTypeParameter[] jtypeParameters) {
     this.name = name;
-    annotations = new Annotations();
-    annotations.addAnnotations(declaredAnnotations);
+    annotations = new Annotations(declaredAnnotations);
 
     if (jtypeParameters != null) {
-      for (JTypeParameter jtypeParameter : jtypeParameters) {
-        addTypeParameter(jtypeParameter);
-      }
+      typeParams = Lists.create(jtypeParameters);
     }
   }
 
@@ -75,7 +73,7 @@
   }
 
   public void addThrows(JType type) {
-    thrownTypes.add(type);
+    thrownTypes = Lists.add(thrownTypes, type);
   }
 
   public JParameter findParameter(String name) {
@@ -216,7 +214,7 @@
   }
 
   void addParameter(JParameter param) {
-    params.add(param);
+    params = Lists.add(params, param);
   }
 
   /**
@@ -248,8 +246,4 @@
     }
     return true;
   }
-
-  private void addTypeParameter(JTypeParameter typeParameter) {
-    typeParams.add(typeParameter);
-  }
 }
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
index 17f0d83..9ce3961 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
@@ -15,8 +15,10 @@
  */
 package com.google.gwt.core.ext.typeinfo;
 
+import com.google.gwt.dev.util.collect.HashSet;
+import com.google.gwt.dev.util.collect.Sets;
+
 import java.lang.annotation.Annotation;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
@@ -32,11 +34,13 @@
    */
   protected static Set<JClassType> getFlattenedSuperTypeHierarchy(
       JClassType type) {
-    if (type.flattenedSupertypes == null) {
-      type.flattenedSupertypes = new HashSet<JClassType>();
-      getFlattenedSuperTypeHierarchyRecursive(type, type.flattenedSupertypes);
+    Set<JClassType> flattened = type.flattenedSupertypes;
+    if (flattened == null) {
+      flattened = new HashSet<JClassType>();
+      getFlattenedSuperTypeHierarchyRecursive(type, flattened);
+      type.flattenedSupertypes = Sets.normalizeUnmodifiable(flattened);
     }
-    return type.flattenedSupertypes;
+    return flattened;
   }
 
   /**
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JField.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JField.java
index 069a06d..d5e7958 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JField.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JField.java
@@ -45,8 +45,7 @@
     this.enclosingType = enclosingType;
     this.name = name;
     this.enclosingType.addField(this);
-    annotations = new Annotations();
-    annotations.addAnnotations(declaredAnnotations);
+    annotations = new Annotations(declaredAnnotations);
   }
 
   JField(JClassType enclosingType, JField srcField) {
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java
index b914c76..18f6681 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java
@@ -16,8 +16,8 @@
 package com.google.gwt.core.ext.typeinfo;
 
 import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType;
+import com.google.gwt.dev.util.collect.Lists;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -27,7 +27,7 @@
 
   private JRawType lazyRawType = null;
 
-  private final List<JTypeParameter> typeParams = new ArrayList<JTypeParameter>();
+  private List<JTypeParameter> typeParams = Lists.create();
 
   public JGenericType(TypeOracle oracle, JPackage declaringPackage,
       JClassType enclosingType, boolean isLocalType, String name,
@@ -109,7 +109,7 @@
   }
 
   private void addTypeParameter(JTypeParameter typeParameter) {
-    typeParams.add(typeParameter);
+    typeParams = Lists.add(typeParams, typeParameter);
     typeParameter.setDeclaringClass(this);
   }
 }
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JPackage.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JPackage.java
index 5db5a59..fbe40da 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JPackage.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JPackage.java
@@ -15,8 +15,9 @@
  */
 package com.google.gwt.core.ext.typeinfo;
 
+import com.google.gwt.dev.util.collect.Maps;
+
 import java.lang.annotation.Annotation;
-import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -28,7 +29,7 @@
 
   private final Annotations annotations = new Annotations();
 
-  private final Map<String, JRealClassType> types = new HashMap<String, JRealClassType>();
+  private Map<String, JRealClassType> types = Maps.create();
 
   JPackage(String name) {
     this.name = name;
@@ -82,7 +83,7 @@
   }
 
   void addType(JRealClassType type) {
-    types.put(type.getSimpleSourceName(), type);
+    types = Maps.put(types, type.getSimpleSourceName(), type);
   }
 
   JClassType findTypeImpl(String[] typeName, int index) {
@@ -111,7 +112,7 @@
   }
 
   void remove(JClassType type) {
-    types.remove(type.getSimpleSourceName());
+    types = Maps.remove(types, type.getSimpleSourceName());
     // JDT will occasionally remove non-existent items, such as packages.
   }
 }
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameter.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameter.java
index da3a2ad..332969f 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameter.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameter.java
@@ -45,8 +45,7 @@
 
     enclosingMethod.addParameter(this);
 
-    annotations = new Annotations();
-    annotations.addAnnotations(declaredAnnotations);
+    annotations = new Annotations(declaredAnnotations);
   }
 
   JParameter(JAbstractMethod enclosingMethod, JParameter srcParam) {
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameterizedType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameterizedType.java
index 19d59ee..b823d7a 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameterizedType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameterizedType.java
@@ -16,10 +16,12 @@
 package com.google.gwt.core.ext.typeinfo;
 
 import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType;
+import com.google.gwt.dev.util.collect.IdentityHashMap;
+import com.google.gwt.dev.util.collect.Lists;
+import com.google.gwt.dev.util.collect.Maps;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -73,7 +75,7 @@
 
   private final AbstractMembers members;
 
-  private final List<JClassType> typeArgs = new ArrayList<JClassType>();
+  private final List<JClassType> typeArgs;
 
   /**
    * This map records the JClassType that should be used in place of a given
@@ -96,9 +98,8 @@
       }
     });
 
-    List<JClassType> typeArgsList = Arrays.asList(typeArgs);
-    this.typeArgs.addAll(typeArgsList);
-    assert (typeArgsList.indexOf(null) == -1);
+    this.typeArgs = Lists.create(typeArgs);
+    assert (this.typeArgs.indexOf(null) == -1);
 
     // NOTE: Can't perform substitutions until we are done building
   }
@@ -158,6 +159,7 @@
         JClassType newIntf = intf.getSubstitutedType(this);
         interfaces.add(newIntf);
       }
+      interfaces = Lists.normalize(interfaces);
     }
     return interfaces.toArray(TypeOracle.NO_JCLASSES);
   }
@@ -457,6 +459,7 @@
       }
       currentParameterizedType = maybeParameterizedType.isParameterized();
     }
+    lazySubstitutionMap = Maps.normalize(lazySubstitutionMap);
   }
 
   /**
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
index d9fbb76..718adee 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
@@ -15,9 +15,10 @@
  */
 package com.google.gwt.core.ext.typeinfo;
 
+import com.google.gwt.dev.util.collect.Lists;
+import com.google.gwt.dev.util.collect.Sets;
+
 import java.lang.annotation.Annotation;
-import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -27,7 +28,7 @@
  */
 public class JRealClassType extends JClassType {
 
-  private final Set<JClassType> allSubtypes = new HashSet<JClassType>();
+  private Set<JClassType> allSubtypes = Sets.create();
 
   private final Annotations annotations = new Annotations();
 
@@ -35,7 +36,7 @@
 
   private final JClassType enclosingType;
 
-  private final List<JClassType> interfaces = new ArrayList<JClassType>();
+  private List<JClassType> interfaces = Lists.create();
 
   private final boolean isInterface;
 
@@ -43,7 +44,7 @@
 
   private String lazyQualifiedName;
 
-  private final AbstractMembers members = new Members(this);
+  private final Members members = new Members(this);
 
   private final HasMetaData metaData = new MetaData();
 
@@ -97,7 +98,7 @@
 
   public void addImplementedInterface(JClassType intf) {
     assert (intf != null);
-    interfaces.add(intf);
+    interfaces = Lists.add(interfaces, intf);
   }
 
   @SuppressWarnings("deprecation")
@@ -427,7 +428,7 @@
 
   protected void acceptSubtype(JClassType me) {
     // TODO(scottb): revisit
-    allSubtypes.add(me);
+    allSubtypes = Sets.add(allSubtypes, me);
     notifySuperTypesOf(me);
   }
 
@@ -494,7 +495,7 @@
 
   protected void removeSubtype(JClassType me) {
     // TODO(scottb): revisit
-    allSubtypes.remove(me);
+    allSubtypes = Sets.remove(allSubtypes, me);
 
     if (superclass != null) {
       superclass.removeSubtype(me);
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/MetaData.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/MetaData.java
index 0966d5e..b5006c3 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/MetaData.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/MetaData.java
@@ -15,9 +15,10 @@
  */
 package com.google.gwt.core.ext.typeinfo;
 
-import java.util.ArrayList;
+import com.google.gwt.dev.util.collect.Lists;
+import com.google.gwt.dev.util.collect.Maps;
+
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -42,17 +43,22 @@
     }
   }
 
-  private final Map<String, List<String[]>> tagNameToStringArrayList = new HashMap<String, List<String[]>>();
+  private Map<String, List<String[]>> tagNameToStringArrayList = Maps.create();
 
+  @SuppressWarnings("unchecked")
   public void addMetaData(String tagName, String[] values) {
     List<String[]> list = tagNameToStringArrayList.get(tagName);
     if (list == null) {
-      list = new ArrayList<String[]>();
-      tagNameToStringArrayList.put(tagName, list);
+      list = (List) Lists.create((Object) values);
+      tagNameToStringArrayList = Maps.put(tagNameToStringArrayList, tagName,
+          list);
+    } else {
+      List<String[]> newList = Lists.add(list, values);
+      if (newList != list) {
+        tagNameToStringArrayList = Maps.put(tagNameToStringArrayList, tagName,
+            newList);
+      }
     }
-    // Yes, we're adding the string array as an object into the list.
-    //
-    list.add(values);
   }
 
   public String[][] getMetaData(String tagName) {
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/TypeOracle.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/TypeOracle.java
index a18b85e..cee006a 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/TypeOracle.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/TypeOracle.java
@@ -21,6 +21,9 @@
 import com.google.gwt.dev.generator.GenUtil;
 import com.google.gwt.dev.jjs.InternalCompilerException;
 import com.google.gwt.dev.shell.JsValueGlue;
+import com.google.gwt.dev.util.collect.HashMap;
+import com.google.gwt.dev.util.collect.HashSet;
+import com.google.gwt.dev.util.collect.IdentityHashMap;
 
 import org.apache.commons.collections.map.AbstractReferenceMap;
 import org.apache.commons.collections.map.ReferenceIdentityMap;
@@ -32,9 +35,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java b/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
index eb0b054..b2b5469 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationUnit.java
@@ -22,6 +22,11 @@
 import com.google.gwt.dev.jdt.TypeRefVisitor;
 import com.google.gwt.dev.shell.CompilingClassLoader;
 import com.google.gwt.dev.util.Util;
+import com.google.gwt.dev.util.collect.HashMap;
+import com.google.gwt.dev.util.collect.HashSet;
+import com.google.gwt.dev.util.collect.IdentityHashMap;
+import com.google.gwt.dev.util.collect.Lists;
+import com.google.gwt.dev.util.collect.Sets;
 
 import org.eclipse.jdt.core.compiler.CategorizedProblem;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
@@ -39,9 +44,6 @@
 import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -280,7 +282,7 @@
         result.add(String.valueOf(referencedType.getFileName()));
       }
     }, cud.scope);
-    return result;
+    return Sets.normalize(result);
   }
 
   /**
@@ -451,7 +453,7 @@
       FindTypesInCud typeFinder = new FindTypesInCud();
       cud.traverse(typeFinder, cud.scope);
       Set<CompiledClass> compiledClasses = typeFinder.getClasses();
-      exposedCompiledClasses = Collections.unmodifiableSet(compiledClasses);
+      exposedCompiledClasses = Sets.normalizeUnmodifiable(compiledClasses);
     }
     return exposedCompiledClasses;
   }
@@ -522,7 +524,7 @@
   }
 
   void setJsniMethods(List<JsniMethod> jsniMethods) {
-    this.jsniMethods = Collections.unmodifiableList(jsniMethods);
+    this.jsniMethods = Lists.normalizeUnmodifiable(jsniMethods);
   }
 
   private List<String> getJdtClassNames(String topLevelClass) {
diff --git a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
index 9649749..ff51cf7 100644
--- a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
+++ b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
@@ -41,6 +41,10 @@
 import com.google.gwt.dev.javac.CompilationUnit.State;
 import com.google.gwt.dev.javac.impl.Shared;
 import com.google.gwt.dev.util.Empty;
+import com.google.gwt.dev.util.collect.HashMap;
+import com.google.gwt.dev.util.collect.HashSet;
+import com.google.gwt.dev.util.collect.IdentityHashMap;
+import com.google.gwt.dev.util.collect.Maps;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
@@ -85,9 +89,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.Array;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -472,7 +473,7 @@
       identifierToValue.put(identifier, elementValue);
     }
 
-    return AnnotationProxyFactory.create(clazz, identifierToValue);
+    return AnnotationProxyFactory.create(clazz, Maps.normalize(identifierToValue));
   }
 
   private JRealClassType createType(CompiledClass compiledClass) {
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java b/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java
index 0220db6..f822206 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java
@@ -15,10 +15,11 @@
  */
 package com.google.gwt.dev.resource.impl;
 
+import com.google.gwt.dev.util.collect.Maps;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -40,7 +41,7 @@
 
   private static class TrieNode {
     // TODO(amitmanjhi): Consider the memory-speed tradeoff here
-    private final Map<String, TrieNode> children = new HashMap<String, TrieNode>();
+    private Map<String, TrieNode> children = Maps.create();
     private final String part;
 
     private PathPrefix prefix;
@@ -51,8 +52,8 @@
 
     public TrieNode addChild(String part) {
       TrieNode newChild = new TrieNode(part);
-      TrieNode oldChild = children.put(part, newChild);
-      assert (oldChild == null);
+      assert !children.containsKey(part);
+      children = Maps.put(children, part, newChild);
       return newChild;
     }
 
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
index 96f37c9..c05b979 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileClassPathEntry.java
@@ -16,13 +16,14 @@
 package com.google.gwt.dev.resource.impl;
 
 import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.dev.util.collect.IdentityHashMap;
+import com.google.gwt.dev.util.collect.IdentityHashSet;
+import com.google.gwt.dev.util.collect.IdentityMaps;
+import com.google.gwt.dev.util.collect.Sets;
 import com.google.gwt.dev.util.msg.Message1String;
 
 import java.io.File;
 import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.zip.ZipEntry;
@@ -65,8 +66,12 @@
   }
 
   private Set<ZipFileResource> allZipFileResources;
-  private final Map<PathPrefixSet, ZipFileSnapshot> cachedSnapshots = new HashMap<PathPrefixSet, ZipFileSnapshot>(
-      2); // currently gwt has just 2 ResourceOracles.
+
+  /**
+   * Currently gwt has just 2 ResourceOracles.
+   */
+  private final Map<PathPrefixSet, ZipFileSnapshot> cachedSnapshots = new IdentityHashMap<PathPrefixSet, ZipFileSnapshot>();
+
   private String cachedLocation;
   private final ZipFile zipFile;
 
@@ -109,7 +114,7 @@
   private Set<ZipFileResource> buildIndex(TreeLogger logger) {
     logger = Messages.BUILDING_INDEX.branch(logger, zipFile.getName(), null);
 
-    HashSet<ZipFileResource> results = new HashSet<ZipFileResource>();
+    Set<ZipFileResource> results = new IdentityHashSet<ZipFileResource>();
     Enumeration<? extends ZipEntry> e = zipFile.entries();
     while (e.hasMoreElements()) {
       ZipEntry zipEntry = e.nextElement();
@@ -121,11 +126,12 @@
         // Skip META-INF since classloaders normally make this invisible.
         continue;
       }
-      ZipFileResource zipResource = new ZipFileResource(this, zipEntry);
+      ZipFileResource zipResource = new ZipFileResource(this,
+          zipEntry.getName());
       results.add(zipResource);
       Messages.READ_ZIP_ENTRY.log(logger, zipEntry.getName(), null);
     }
-    return results;
+    return Sets.normalize(results);
   }
 
   private Map<AbstractResource, PathPrefix> computeApplicableResources(
@@ -144,6 +150,6 @@
         Messages.EXCLUDING_RESOURCE.log(logger, path, null);
       }
     }
-    return results;
+    return IdentityMaps.normalize(results);
   }
 }
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java
index 3c15743..bfd6432 100644
--- a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java
+++ b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java
@@ -19,7 +19,7 @@
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
 import java.util.zip.ZipEntry;
 
 /**
@@ -28,11 +28,11 @@
 public class ZipFileResource extends AbstractResource {
 
   private final ZipFileClassPathEntry classPathEntry;
-  private final ZipEntry zipEntry;
+  private final String path;
 
-  public ZipFileResource(ZipFileClassPathEntry classPathEntry, ZipEntry zipEntry) {
+  public ZipFileResource(ZipFileClassPathEntry classPathEntry, String path) {
     this.classPathEntry = classPathEntry;
-    this.zipEntry = zipEntry;
+    this.path = path;
   }
 
   @Override
@@ -42,21 +42,21 @@
 
   @Override
   public long getLastModified() {
-    // Questionable: maybe we should do something with the jar's time instead.
-    return zipEntry.getTime();
+    return getEntry().getTime();
   }
 
   @Override
   public String getLocation() {
     // CHECKSTYLE_OFF
-    String proto = zipEntry instanceof JarEntry ? "jar:" : "zip:";
+    String proto = classPathEntry.getZipFile() instanceof JarFile ? "jar:"
+        : "zip:";
     // CHECKSTYLE_ON
-    return proto + classPathEntry.getLocation() + "!/" + getPath();
+    return proto + classPathEntry.getLocation() + "!/" + path;
   }
 
   @Override
   public String getPath() {
-    return zipEntry.getName();
+    return path;
   }
 
   @Override
@@ -68,10 +68,6 @@
     }
   }
 
-  public ZipEntry getZipEntry() {
-    return zipEntry;
-  }
-
   /**
    * Since we don't dynamically reload zips during a run, zip-based resources
    * cannot become stale.
@@ -84,7 +80,7 @@
   @Override
   public InputStream openContents() {
     try {
-      return classPathEntry.getZipFile().getInputStream(zipEntry);
+      return classPathEntry.getZipFile().getInputStream(getEntry());
     } catch (IOException e) {
       // The spec for this method says it can return null.
       return null;
@@ -95,4 +91,8 @@
   public boolean wasRerooted() {
     return false;
   }
+
+  private ZipEntry getEntry() {
+    return classPathEntry.getZipFile().getEntry(path);
+  }
 }
diff --git a/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java b/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
index 6ace93c..34b10a2 100644
--- a/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
+++ b/dev/core/src/com/google/gwt/dev/shell/StandardGeneratorContext.java
@@ -31,6 +31,8 @@
 import com.google.gwt.dev.javac.CompilationUnit;
 import com.google.gwt.dev.javac.impl.Shared;
 import com.google.gwt.dev.util.Util;
+import com.google.gwt.dev.util.collect.HashSet;
+import com.google.gwt.dev.util.collect.IdentityHashMap;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -38,8 +40,6 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/AnnotationsTest.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/AnnotationsTest.java
index 14669e4..4fafeb1 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/AnnotationsTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/AnnotationsTest.java
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.core.ext.typeinfo;
 
+import com.google.gwt.dev.util.collect.IdentityHashMap;
+
 import junit.framework.TestCase;
 
 import java.lang.annotation.Annotation;
@@ -52,7 +54,6 @@
     String value();
   }
 
-  
   @Inherited
   @Retention(RetentionPolicy.RUNTIME)
   @Target(ElementType.TYPE)
@@ -66,10 +67,12 @@
   private static Annotations initializeAnnotationsFromClass(
       Class<?> annotatedClass, Annotations parent) {
     Annotation[] jAnnotations = annotatedClass.getDeclaredAnnotations();
-    Annotations annotations = new Annotations();
+
+    Map<Class<? extends Annotation>, Annotation> map = new IdentityHashMap<Class<? extends Annotation>, Annotation>();
     for (Annotation annotation : jAnnotations) {
-      annotations.addAnnotation(annotation.annotationType(), annotation);
+      map.put(annotation.annotationType(), annotation);
     }
+    Annotations annotations = new Annotations(map);
 
     if (parent != null) {
       annotations.setParent(parent);
@@ -85,7 +88,8 @@
   public void testAddAnnotations() {
     Annotations annotations = new Annotations();
     Map<Class<? extends Annotation>, Annotation> entries = new HashMap<Class<? extends Annotation>, Annotation>();
-    entries.put(TestAnnotation1.class, AnnotatedClass1.class.getAnnotation(TestAnnotation1.class));
+    entries.put(TestAnnotation1.class,
+        AnnotatedClass1.class.getAnnotation(TestAnnotation1.class));
     annotations.addAnnotations(entries);
     assertNotNull(annotations.getAnnotation(TestAnnotation1.class));
   }