Speedup `unused` compress option for already minified code
authorkzc <zaxxon2011@gmail.com>
Mon, 28 Mar 2016 21:58:50 +0000 (17:58 -0400)
committerkzc <zaxxon2011@gmail.com>
Mon, 28 Mar 2016 21:58:50 +0000 (17:58 -0400)
Fixes: #321 #917 #1022

lib/compress.js
lib/scope.js

index f49486a..4f37e83 100644 (file)
@@ -1242,6 +1242,7 @@ merge(Compressor.prototype, {
             && !self.uses_eval
            ) {
             var in_use = [];
+            var in_use_ids = {}; // avoid expensive linear scans of in_use
             var initializations = new Dictionary();
             // pass 1: find out which symbols are directly used in
             // this scope (not in nested scopes).
@@ -1264,7 +1265,11 @@ merge(Compressor.prototype, {
                         return true;
                     }
                     if (node instanceof AST_SymbolRef) {
-                        push_uniq(in_use, node.definition());
+                        var node_def = node.definition();
+                        if (!(node_def.id in in_use_ids)) {
+                            in_use_ids[node_def.id] = true;
+                            in_use.push(node_def);
+                        }
                         return true;
                     }
                     if (node instanceof AST_Scope) {
@@ -1287,7 +1292,11 @@ merge(Compressor.prototype, {
                     if (init) init.forEach(function(init){
                         var tw = new TreeWalker(function(node){
                             if (node instanceof AST_SymbolRef) {
-                                push_uniq(in_use, node.definition());
+                                var node_def = node.definition();
+                                if (!(node_def.id in in_use_ids)) {
+                                    in_use_ids[node_def.id] = true;
+                                    in_use.push(node_def);
+                                }
                             }
                         });
                         init.walk(tw);
@@ -1315,7 +1324,7 @@ merge(Compressor.prototype, {
                         }
                     }
                     if (node instanceof AST_Defun && node !== self) {
-                        if (!member(node.name.definition(), in_use)) {
+                        if (!(node.name.definition().id in in_use_ids)) {
                             compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", {
                                 name : node.name.name,
                                 file : node.name.start.file,
@@ -1328,7 +1337,7 @@ merge(Compressor.prototype, {
                     }
                     if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
                         var def = node.definitions.filter(function(def){
-                            if (member(def.name.definition(), in_use)) return true;
+                            if (def.name.definition().id in in_use_ids) return true;
                             var w = {
                                 name : def.name.name,
                                 file : def.name.start.file,
index 5ab775a..d07eca1 100644 (file)
@@ -53,8 +53,11 @@ function SymbolDef(scope, index, orig) {
     this.undeclared = false;
     this.constant = false;
     this.index = index;
+    this.id = SymbolDef.next_id++;
 };
 
+SymbolDef.next_id = 1;
+
 SymbolDef.prototype = {
     unmangleable: function(options) {
         if (!options) options = {};