Avoid a linear search when generating identifier names in the inliner and pretty namer.

Review by: scottb@google.com



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5483 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/js/JsInliner.java b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
index faad0bb..f3e974c 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsInliner.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
@@ -63,6 +63,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.List;
@@ -727,6 +728,13 @@
     private final JsProgram program;
 
     /**
+     * A map containing the next integer to try as an identifier suffix for
+     * a given JsScope.
+     */
+    private IdentityHashMap<JsScope,HashMap<String,Integer>> startIdentForScope
+        = new IdentityHashMap<JsScope, HashMap<String,Integer>>();
+
+    /**
      * Not a stack because program fragments aren't nested.
      */
     private JsFunction programFunction;
@@ -961,11 +969,20 @@
          * function so we'll use a counter for disambiguation.
          */
         String ident;
-        int count = 0;
+        String base = f.getName() + "_" + name.getIdent();
         JsScope scope = functionStack.peek().getScope();
+        HashMap<String,Integer> startIdent = startIdentForScope.get(scope);
+        if (startIdent == null) {
+          startIdent = new HashMap<String,Integer>();
+          startIdentForScope.put(scope, startIdent);
+        }
+        
+        Integer s = startIdent.get(base);
+        int suffix = (s == null) ? 0 : s.intValue();
         do {
-          ident = f.getName() + "_" + name.getIdent() + "_" + count++;
+          ident = base + "_" + suffix++;
         } while (scope.findExistingName(ident) != null);
+        startIdent.put(base, suffix);
 
         JsName newName = scope.declareName(ident, name.getShortIdent());
         v.setReplacementName(name, newName);
diff --git a/dev/core/src/com/google/gwt/dev/js/JsPrettyNamer.java b/dev/core/src/com/google/gwt/dev/js/JsPrettyNamer.java
index a445af8..db47892 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsPrettyNamer.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsPrettyNamer.java
@@ -20,7 +20,9 @@
 import com.google.gwt.dev.js.ast.JsRootScope;
 import com.google.gwt.dev.js.ast.JsScope;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -40,6 +42,13 @@
   private Set<String> childIdents = null;
 
   private final JsProgram program;
+  
+  /**
+   * A map containing the next integer to try as an identifier suffix for
+   * a given JsScope.
+   */
+  private IdentityHashMap<JsScope,HashMap<String,Integer>> startIdentForScope =
+    new IdentityHashMap<JsScope, HashMap<String,Integer>>();
 
   public JsPrettyNamer(JsProgram program) {
     this.program = program;
@@ -66,6 +75,12 @@
   }
 
   private void visit(JsScope scope) {
+    HashMap<String,Integer> startIdent = startIdentForScope.get(scope);
+    if (startIdent == null) {
+      startIdent = new HashMap<String,Integer>();
+      startIdentForScope.put(scope, startIdent);
+    }
+    
     // Save off the childIdents which is currently being computed for my parent.
     Set<String> myChildIdents = childIdents;
 
@@ -95,13 +110,17 @@
 
       String newIdent = name.getShortIdent();
       if (!isLegal(scope, childIdents, newIdent)) {
-        String checkIdent = newIdent;
-        for (int i = 0; true; ++i) {
-          checkIdent = newIdent + "_" + i;
-          if (isLegal(scope, childIdents, checkIdent)) {
-            break;
-          }
-        }
+        String checkIdent;
+        
+        // Start searching using a suffix hint stored in the scope.
+        // We still do a search in case there is a collision with
+        // a user-provided identifier
+        Integer s = startIdent.get(newIdent);
+        int suffix = (s == null) ? 0 : s.intValue();
+        do {
+          checkIdent = newIdent + "_" + suffix++;
+        } while (!isLegal(scope, childIdents, checkIdent));
+        startIdent.put(newIdent, suffix);
         name.setShortIdent(checkIdent);
       } else {
         // nothing to do; the short name is already good