From 16411dcb8721e9901271db74c3409e720c2f8ec5 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sat, 1 May 2021 14:37:52 +0100 Subject: [PATCH] enhance `collapse_vars` (#4885) --- lib/compress.js | 69 +++++++++++++++++++--------------- test/compress/collapse_vars.js | 2 +- test/compress/hoist_vars.js | 3 +- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 26bcbc72be..9201d890c8 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1902,6 +1902,7 @@ merge(Compressor.prototype, { hit_stack = candidates.pop(); var hit_index = 0; var candidate = hit_stack[hit_stack.length - 1]; + var remaining; var value_def = null; var stop_after = null; var stop_if_hit = null; @@ -1944,25 +1945,22 @@ merge(Compressor.prototype, { statements[i].transform(scanner); } if (value_def) { - var def = lhs.definition(); - var referenced = def.references.length - def.replaced; - if (candidate instanceof AST_Assign) referenced--; - if (!replaced || referenced > replaced) { + if (!replaced || remaining > replaced) { candidates.push(hit_stack); force_single = true; continue; } + var def = lhs.definition(); abort = false; hit_index = 0; hit = funarg; for (var i = stat_index; !abort && i < statements.length; i++) { if (!statements[i].transform(multi_replacer)) statements.splice(i--, 1); } - if (candidate !== hit_stack[hit_stack.length - 1]) { - replaced = false; - } else if (candidate instanceof AST_VarDef) { - replaced = !compressor.exposed(def) && def.references.length == def.replaced; - } + replaced = candidate instanceof AST_VarDef + && candidate === hit_stack[hit_stack.length - 1] + && def.references.length == def.replaced + && !compressor.exposed(def); value_def.last_ref = false; value_def.single_use = false; } @@ -2252,7 +2250,7 @@ merge(Compressor.prototype, { if (!arg) continue; var candidate = make_node(AST_VarDef, sym, { name: sym, - value: arg + value: arg, }); candidate.name_index = i; candidate.arg_index = value ? len + i : i; @@ -2268,12 +2266,11 @@ merge(Compressor.prototype, { extract_candidates(node, unused); }); } else if (expr instanceof AST_Assign) { - if (!(expr.left instanceof AST_Destructured)) candidates.push(hit_stack.slice()); - extract_candidates(expr.left); + var lhs = expr.left; + if (!(lhs instanceof AST_Destructured)) candidates.push(hit_stack.slice()); + extract_candidates(lhs); extract_candidates(expr.right); - if (expr.left instanceof AST_SymbolRef) { - assignments[expr.left.name] = (assignments[expr.left.name] || 0) + 1; - } + if (lhs instanceof AST_SymbolRef) assignments[lhs.name] = (assignments[lhs.name] || 0) + 1; } else if (expr instanceof AST_Await) { extract_candidates(expr.expression, unused); } else if (expr instanceof AST_Binary) { @@ -2555,6 +2552,7 @@ merge(Compressor.prototype, { force_single = false; return; } + if (remaining < 1) return; var value = rhs instanceof AST_Assign && rhs.operator == "=" ? rhs.left : rhs; if (!(value instanceof AST_SymbolRef)) return; var def = value.definition(); @@ -2577,32 +2575,41 @@ merge(Compressor.prototype, { function get_lhs(expr) { if (expr instanceof AST_Assign) { - var def, lhs = expr.left; - if (expr.operator == "=" - && lhs instanceof AST_SymbolRef - && (def = lhs.definition()).references[0] === lhs - && !(scope.uses_arguments && is_funarg(def)) - && !compressor.exposed(def)) { - var referenced = def.references.length - def.replaced; - if (referenced > 1) mangleable_var(expr.right); - } + var lhs = expr.left; + if (expr.operator != "=") return lhs; + if (!(lhs instanceof AST_SymbolRef)) return lhs; + var def = lhs.definition(); + if (scope.uses_arguments && is_funarg(def)) return lhs; + if (compressor.exposed(def)) return lhs; + remaining = def.references.length - def.replaced - (assignments[def.name] || 0); + if (def.fixed && lhs.fixed) remaining = Math.min(remaining, def.references.filter(function(ref) { + return ref.fixed === lhs.fixed; + }).length - 1); + mangleable_var(expr.right); return lhs; } if (expr instanceof AST_Binary) return expr.right.left; if (expr instanceof AST_Unary) return expr.expression; if (expr instanceof AST_VarDef) { - var def = expr.name.definition(); + var lhs = expr.name; + var def = lhs.definition(); if (def.const_redefs) return; - if (!member(expr.name, def.orig)) return; + if (!member(lhs, def.orig)) return; if (scope.uses_arguments && is_funarg(def)) return; var declared = def.orig.length - def.eliminated - (declare_only[def.name] || 0); - var referenced = def.references.length - def.replaced - (assignments[def.name] || 0); - if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg)) { + remaining = def.references.length - def.replaced - (assignments[def.name] || 0); + if (def.fixed) remaining = Math.min(remaining, def.references.filter(function(ref) { + if (!ref.fixed) return true; + if (!ref.fixed.assigns) return true; + var assign = ref.fixed.assigns[0]; + return assign === lhs || get_rvalue(assign) === expr.value; + }).length); + if (declared > 1 && !(lhs instanceof AST_SymbolFunarg)) { mangleable_var(expr.value); - return make_node(AST_SymbolRef, expr.name, expr.name); + return make_node(AST_SymbolRef, lhs, lhs); } - if (mangleable_var(expr.value) || referenced == 1 && !compressor.exposed(def)) { - return make_node(AST_SymbolRef, expr.name, expr.name); + if (mangleable_var(expr.value) || remaining == 1 && !compressor.exposed(def)) { + return make_node(AST_SymbolRef, lhs, lhs); } return; } diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index 071ee16284..449ce3d5f2 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -4724,7 +4724,7 @@ cascade_statement: { } function f3(a, b) { for (; a < b; a++) - if ((c = a) && b) + if (c = a, a && b) var c = c = b(a); } } diff --git a/test/compress/hoist_vars.js b/test/compress/hoist_vars.js index a6efa7af08..4ca2ce5b5b 100644 --- a/test/compress/hoist_vars.js +++ b/test/compress/hoist_vars.js @@ -232,8 +232,9 @@ issue_4736: { expect: { (function() { (function() { + var b = 1 << 30; 0, - console.log(1073741824); + console.log(b); })(); })(); }