[Pkg-javascript-commits] [uglifyjs] 204/228: optimise `do{...}while(false)` (#1785)

Jonas Smedegaard dr at jones.dk
Sat Apr 15 14:25:30 UTC 2017


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository uglifyjs.

commit 9b6bc67c3393507d0621eb3debbe8845b0eff52d
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Tue Apr 4 23:48:22 2017 +0800

    optimise `do{...}while(false)` (#1785)
    
    - better heuristics to avoid issues like #1532
    - fix `TreeWalker.loopcontrol_target()`
      - `continue` cannot refer to `switch` blocks
---
 lib/ast.js             | 10 +++++-----
 lib/compress.js        | 32 ++++++++++++++++++++------------
 test/compress/loops.js | 26 ++++++++++++++++++++++++--
 3 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/lib/ast.js b/lib/ast.js
index 092a959..ba1330f 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -1035,16 +1035,16 @@ TreeWalker.prototype = {
             self = p;
         }
     },
-    loopcontrol_target: function(label) {
+    loopcontrol_target: function(node) {
         var stack = this.stack;
-        if (label) for (var i = stack.length; --i >= 0;) {
+        if (node.label) for (var i = stack.length; --i >= 0;) {
             var x = stack[i];
-            if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
+            if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)
                 return x.body;
-            }
         } else for (var i = stack.length; --i >= 0;) {
             var x = stack[i];
-            if (x instanceof AST_Switch || x instanceof AST_IterationStatement)
+            if (x instanceof AST_IterationStatement
+                || node instanceof AST_Break && x instanceof AST_Switch)
                 return x;
         }
     }
diff --git a/lib/compress.js b/lib/compress.js
index 79e7d4d..14083fe 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -893,7 +893,7 @@ merge(Compressor.prototype, {
                     }
 
                     var ab = aborts(stat.body);
-                    var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
+                    var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
                     if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
                                || (ab instanceof AST_Continue && self === loop_body(lct))
                                || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
@@ -915,7 +915,7 @@ merge(Compressor.prototype, {
                     }
 
                     var ab = aborts(stat.alternative);
-                    var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
+                    var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
                     if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
                                || (ab instanceof AST_Continue && self === loop_body(lct))
                                || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
@@ -964,7 +964,7 @@ merge(Compressor.prototype, {
                     extract_declarations_from_unreachable_code(compressor, stat, a);
                 } else {
                     if (stat instanceof AST_LoopControl) {
-                        var lct = compressor.loopcontrol_target(stat.label);
+                        var lct = compressor.loopcontrol_target(stat);
                         if ((stat instanceof AST_Break
                              && !(lct instanceof AST_IterationStatement)
                              && loop_body(lct) === self) || (stat instanceof AST_Continue
@@ -1746,7 +1746,7 @@ merge(Compressor.prototype, {
 
     OPT(AST_LabeledStatement, function(self, compressor){
         if (self.body instanceof AST_Break
-            && compressor.loopcontrol_target(self.body.label) === self.body) {
+            && compressor.loopcontrol_target(self.body) === self.body) {
             return make_node(AST_EmptyStatement, self);
         }
         return self.label.references.length == 0 ? self.body : self;
@@ -2314,13 +2314,21 @@ merge(Compressor.prototype, {
                 return make_node(AST_For, self, {
                     body: self.body
                 });
-            } else if (compressor.option("dead_code") && self instanceof AST_While) {
+            }
+            if (compressor.option("dead_code") && self instanceof AST_While) {
                 var a = [];
                 extract_declarations_from_unreachable_code(compressor, self.body, a);
                 return make_node(AST_BlockStatement, self, { body: a });
-            } else {
-                cond = make_node_from_constant(cond, self.condition).transform(compressor);
-                self.condition = best_of_expression(cond, self.condition);
+            }
+            if (self instanceof AST_Do) {
+                var has_loop_control = false;
+                var tw = new TreeWalker(function(node) {
+                    if (node instanceof AST_Scope || has_loop_control) return true;
+                    if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
+                        return has_loop_control = true;
+                });
+                self.walk(tw);
+                if (!has_loop_control) return self.body;
             }
         }
         if (self instanceof AST_While) {
@@ -2346,7 +2354,7 @@ merge(Compressor.prototype, {
         var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
         if (first instanceof AST_If) {
             if (first.body instanceof AST_Break
-                && compressor.loopcontrol_target(first.body.label) === compressor.self()) {
+                && compressor.loopcontrol_target(first.body) === compressor.self()) {
                 if (self.condition) {
                     self.condition = make_node(AST_Binary, self.condition, {
                         left: self.condition,
@@ -2359,7 +2367,7 @@ merge(Compressor.prototype, {
                 drop_it(first.alternative);
             }
             else if (first.alternative instanceof AST_Break
-                     && compressor.loopcontrol_target(first.alternative.label) === compressor.self()) {
+                     && compressor.loopcontrol_target(first.alternative) === compressor.self()) {
                 if (self.condition) {
                     self.condition = make_node(AST_Binary, self.condition, {
                         left: self.condition,
@@ -2590,7 +2598,7 @@ merge(Compressor.prototype, {
         self.body = body;
         while (branch = body[body.length - 1]) {
             var stat = branch.body[branch.body.length - 1];
-            if (stat instanceof AST_Break && compressor.loopcontrol_target(stat.label) === self)
+            if (stat instanceof AST_Break && compressor.loopcontrol_target(stat) === self)
                 branch.body.pop();
             if (branch.body.length || branch instanceof AST_Case
                 && (default_branch || branch.expression.has_side_effects(compressor))) break;
@@ -2609,7 +2617,7 @@ merge(Compressor.prototype, {
                 if (has_break
                     || node instanceof AST_Lambda
                     || node instanceof AST_SimpleStatement) return true;
-                if (node instanceof AST_Break && tw.loopcontrol_target(node.label) === self)
+                if (node instanceof AST_Break && tw.loopcontrol_target(node) === self)
                     has_break = true;
             });
             self.walk(tw);
diff --git a/test/compress/loops.js b/test/compress/loops.js
index c8d7784..f13f5cc 100644
--- a/test/compress/loops.js
+++ b/test/compress/loops.js
@@ -215,8 +215,7 @@ evaluate: {
             a();
         for(;;)
             c();
-        // rule disabled due to issue_1532
-        do d(); while (false);
+        d();
     }
 }
 
@@ -458,3 +457,26 @@ issue_1648: {
     }
     expect_exact: "function f(){for(x();1;);}"
 }
+
+do_switch: {
+    options = {
+        evaluate: true,
+        loops: true,
+    }
+    input: {
+        do {
+            switch (a) {
+              case b:
+                continue;
+            }
+        } while (false);
+    }
+    expect: {
+        do {
+            switch (a) {
+              case b:
+                continue;
+            }
+        } while (false);
+    }
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git



More information about the Pkg-javascript-commits mailing list