From 8646b15314d656408de7a734f32a0f49be9bd3b5 Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Tue, 20 Sep 2016 22:23:27 +0800 Subject: [PATCH 1/7] optimize unmodified variables --- lib/compress.js | 3 +- lib/scope.js | 11 ++++--- test/compress/reduce_vars.js | 60 ++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 test/compress/reduce_vars.js diff --git a/lib/compress.js b/lib/compress.js index 8a08572f..bfb476cf 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -67,6 +67,7 @@ function Compressor(options, false_by_default) { if_return : !false_by_default, join_vars : !false_by_default, collapse_vars : false, + reduce_vars : false, cascade : !false_by_default, side_effects : !false_by_default, pure_getters : false, @@ -1107,7 +1108,7 @@ merge(Compressor.prototype, { this._evaluating = true; try { var d = this.definition(); - if (d && d.constant && d.init) { + if (d && (d.constant || compressor.option("reduce_vars") && !d.global && !d.modified) && d.init) { return ev(d.init, compressor); } } finally { diff --git a/lib/scope.js b/lib/scope.js index 606a5a2f..32059c07 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -197,7 +197,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ } if (node instanceof AST_SymbolRef) { var name = node.name; - if (name == "eval" && tw.parent() instanceof AST_Call) { + var parent = tw.parent(); + if (name == "eval" && parent instanceof AST_Call) { for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) { s.uses_eval = true; } @@ -213,12 +214,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ g.global = true; globals.set(name, g); } - node.thedef = g; + sym = g; if (func && name == "arguments") { func.uses_arguments = true; } - } else { - node.thedef = sym; + } + node.thedef = sym; + if (parent instanceof AST_Assign || parent instanceof AST_Unary && (parent.operator === '++' || parent.operator === '--')) { + sym.modified = true; } node.reference(); return true; diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js new file mode 100644 index 00000000..144f4239 --- /dev/null +++ b/test/compress/reduce_vars.js @@ -0,0 +1,60 @@ +reduce_vars: { + options = { + conditionals : true, + evaluate : true, + global_defs : { + C : 0 + }, + reduce_vars : true, + unused : true + } + input: { + var A = 1; + (function f0() { + var a = 2; + console.log(a - 5); + console.log(A - 5); + })(); + (function f1() { + var a = 2; + console.log(a - 5); + eval("console.log(a);"); + })(); + (function f2(eval) { + var a = 2; + console.log(a - 5); + eval("console.log(a);"); + })(eval); + (function f3() { + var b = typeof C !== "undefined"; + var c = 4; + if (b) { + return 'yes'; + } else { + return 'no'; + } + })(); + console.log(A + 1); + } + expect: { + var A = 1; + (function() { + console.log(-3); + console.log(A - 5); + })(); + (function f1() { + var a = 2; + console.log(-3); + eval("console.log(a);"); + })(); + (function f2(eval) { + var a = 2; + console.log(-3); + eval("console.log(a);"); + })(eval); + (function() { + return "yes"; + })(); + console.log(A + 1); + } +} From 5ad6a0e2cab9d827f4b755b5fa3921f8d880aa5a Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Wed, 21 Sep 2016 00:23:56 +0800 Subject: [PATCH 2/7] only mark LHS as modified in assignments --- lib/scope.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/scope.js b/lib/scope.js index 32059c07..fb583291 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -220,7 +220,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ } } node.thedef = sym; - if (parent instanceof AST_Assign || parent instanceof AST_Unary && (parent.operator === '++' || parent.operator === '--')) { + if (parent instanceof AST_Unary && (parent.operator === '++' || parent.operator === '--') + || parent instanceof AST_Assign && parent.left === node) { sym.modified = true; } node.reference(); From dd3e5bcd817ae1f49fbb7770299437b301669f5a Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Wed, 21 Sep 2016 00:24:11 +0800 Subject: [PATCH 3/7] add more tests --- test/compress/reduce_vars.js | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 144f4239..6fcaf2e5 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -58,3 +58,70 @@ reduce_vars: { console.log(A + 1); } } + +modified: { + options = { + conditionals : true, + evaluate : true, + reduce_vars : true, + unused : true + } + input: { + function f0() { + var a = 1, b = 2; + b++; + console.log(a + 1); + console.log(b + 1); + } + + function f1() { + var a = 1, b = 2, c = 3; + b = c; + console.log(a + b); + console.log(b + c); + console.log(a + c); + console.log(a + b + c); + } + + function f2() { + var a = 1, b = 2, c = 3; + if (a) { + b = c; + } else { + c = b; + } + console.log(a + b); + console.log(b + c); + // TODO: as "modified" is determined in "figure_out_scope", + // even "passes" would improve this any further + console.log(a + c); + console.log(a + b + c); + } + } + expect: { + function f0() { + var b = 2; + b++; + console.log(2); + console.log(b + 1); + } + + function f1() { + var a = 1, b = 2, c = 3; + b = c; + console.log(a + b); + console.log(b + c); + console.log(4); + console.log(a + b + c); + } + + function f2() { + var a = 1, b = 2, c = 3; + b = c; + console.log(a + b); + console.log(b + c); + console.log(a + c); + console.log(a + b + c); + } + } +} \ No newline at end of file From 75f3ed202c0b7b2194bf54f7ab9a9412711cd8cd Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Wed, 21 Sep 2016 00:25:04 +0800 Subject: [PATCH 4/7] add documentation --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e0aa4ba9..ed2630f1 100644 --- a/README.md +++ b/README.md @@ -348,6 +348,9 @@ to set `true`; it's effectively a shortcut for `foo=true`). - `collapse_vars` -- default `false`. Collapse single-use `var` and `const` definitions when possible. +- `reduce_vars` -- default `false`. Improve optimization on variables assigned + with and used as constant values. + - `warnings` -- display warnings when dropping unreachable code or unused declarations etc. From 8c3697c50469b8710abe827b7e7c8e4128d02c8c Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Wed, 21 Sep 2016 01:44:27 +0800 Subject: [PATCH 5/7] optimize top-level variables as well --- lib/compress.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/compress.js b/lib/compress.js index bfb476cf..14fb8f1e 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1108,7 +1108,7 @@ merge(Compressor.prototype, { this._evaluating = true; try { var d = this.definition(); - if (d && (d.constant || compressor.option("reduce_vars") && !d.global && !d.modified) && d.init) { + if (d && (d.constant || compressor.option("reduce_vars") && !d.modified) && d.init) { return ev(d.init, compressor); } } finally { From fe1979bf0b635ab4e066bedb9c7fdd4c09c039ef Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Wed, 21 Sep 2016 01:44:34 +0800 Subject: [PATCH 6/7] add more tests --- test/compress/reduce_vars.js | 54 ++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 6fcaf2e5..15718ff6 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -40,7 +40,7 @@ reduce_vars: { var A = 1; (function() { console.log(-3); - console.log(A - 5); + console.log(-4); })(); (function f1() { var a = 2; @@ -55,7 +55,7 @@ reduce_vars: { (function() { return "yes"; })(); - console.log(A + 1); + console.log(2); } } @@ -75,6 +75,13 @@ modified: { } function f1() { + var a = 1, b = 2; + --b; + console.log(a + 1); + console.log(b + 1); + } + + function f2() { var a = 1, b = 2, c = 3; b = c; console.log(a + b); @@ -83,7 +90,16 @@ modified: { console.log(a + b + c); } - function f2() { + function f3() { + var a = 1, b = 2, c = 3; + b *= c; + console.log(a + b); + console.log(b + c); + console.log(a + c); + console.log(a + b + c); + } + + function f4() { var a = 1, b = 2, c = 3; if (a) { b = c; @@ -97,6 +113,12 @@ modified: { console.log(a + c); console.log(a + b + c); } + + function f5(a) { + B = a; + console.log(A ? 'yes' : 'no'); + console.log(B ? 'yes' : 'no'); + } } expect: { function f0() { @@ -107,6 +129,13 @@ modified: { } function f1() { + var b = 2; + --b; + console.log(2); + console.log(b + 1); + } + + function f2() { var a = 1, b = 2, c = 3; b = c; console.log(a + b); @@ -115,7 +144,16 @@ modified: { console.log(a + b + c); } - function f2() { + function f3() { + var a = 1, b = 2, c = 3; + b *= c; + console.log(a + b); + console.log(b + c); + console.log(4); + console.log(a + b + c); + } + + function f4() { var a = 1, b = 2, c = 3; b = c; console.log(a + b); @@ -123,5 +161,11 @@ modified: { console.log(a + c); console.log(a + b + c); } - } + + function f5(a) { + B = a; + console.log(A ? 'yes' : 'no'); + console.log(B ? 'yes' : 'no'); + } + } } \ No newline at end of file From d812195ace6b3408adbbf5fdcc31f2f9011e26d9 Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Wed, 21 Sep 2016 02:06:21 +0800 Subject: [PATCH 7/7] fix typo --- test/compress/reduce_vars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 15718ff6..a1d05012 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -109,7 +109,7 @@ modified: { console.log(a + b); console.log(b + c); // TODO: as "modified" is determined in "figure_out_scope", - // even "passes" would improve this any further + // even "passes" wouldn't improve this any further console.log(a + c); console.log(a + b + c); }