Change JsScope to use LinkedHashMap instead of HashMap. This allows identifiers to be allocated obfuscated identifiers in the original order of their declaration, which produces a lot more common substrings in the obfuscated output which significantly improves gzip/deflate compression. Experimental Data using gzip -9 on cache.html files:

Mail sample: 191614/197548 (3%) (with patch/without/% improved)
Chronoscope: 1373800/1482204 (7.3%)
Showcase: 1641005/1832098 (10.5%)



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5865 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
index 71489d6..de9552a 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
@@ -24,7 +24,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.TreeMap;
 
 /**
  * A scope is a factory for creating and allocating
@@ -162,11 +161,7 @@
    * Returns an iterator for all the names defined by this scope.
    */
   public Iterator<JsName> getAllNames() {
-    if (names.size() > 1) {
-      return new TreeMap<String, JsName>(names).values().iterator();
-    } else {
       return names.values().iterator();
-    }
   }
 
   /**
@@ -206,7 +201,7 @@
    */
   protected JsName doCreateName(String ident, String shortIdent) {
     JsName name = new JsName(this, ident, shortIdent);
-    names = Maps.put(names, ident, name);
+    names = Maps.putOrdered(names, ident, name);
     return name;
   }
 
diff --git a/dev/core/src/com/google/gwt/dev/util/collect/Maps.java b/dev/core/src/com/google/gwt/dev/util/collect/Maps.java
index 98fd25e..1cc6899 100644
--- a/dev/core/src/com/google/gwt/dev/util/collect/Maps.java
+++ b/dev/core/src/com/google/gwt/dev/util/collect/Maps.java
@@ -17,6 +17,7 @@
 

 import java.util.Collections;

 import java.util.Map;

+import java.util.LinkedHashMap;

 

 /**

  * Utility methods for operating on memory-efficient maps. All maps of size 0 or

@@ -117,6 +118,32 @@
     }

   }

 

+  /**

+   * A variation of the put method which uses a LinkedHashMap.

+   */

+  public static <K, V> Map<K, V> putOrdered(Map<K, V> map, K key, V value) {

+    switch (map.size()) {

+      case 0:

+        // Empty -> Singleton

+        return Collections.singletonMap(key, value);

+      case 1: {

+        if (map.containsKey(key)) {

+          return create(key, value);

+        }

+        // Singleton -> LinkedHashMap

+        Map<K, V> result = new LinkedHashMap<K, V>();

+        result.put(map.keySet().iterator().next(),

+            map.values().iterator().next());

+        result.put(key, value);

+        return result;

+      }

+      default:

+        // LinkedHashMap

+        map.put(key, value);

+        return map;

+    }

+  }

+

   public static <K, V> Map<K, V> remove(Map<K, V> map, K key) {

     switch (map.size()) {

       case 0: