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