Skip to content

Commit

Permalink
enhance reduce_vars (#5636)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl authored Aug 30, 2022
1 parent 15b608f commit 10bc86b
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 40 deletions.
94 changes: 69 additions & 25 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -621,8 +621,10 @@ Compressor.prototype.compress = function(node) {
scope.may_call_this = undefined;
}

function push(tw) {
tw.safe_ids = Object.create(tw.safe_ids);
function push(tw, sequential) {
var safe_ids = Object.create(tw.safe_ids);
if (!sequential) safe_ids.seq = {};
tw.safe_ids = safe_ids;
}

function pop(tw) {
Expand All @@ -643,7 +645,14 @@ Compressor.prototype.compress = function(node) {
var safe = tw.safe_ids[def.id];
if (safe) {
var in_order = HOP(tw.safe_ids, def.id);
if (!in_order) safe.read = safe.read && safe.read !== tw.safe_ids ? true : tw.safe_ids;
if (!in_order) {
var seq = tw.safe_ids.seq;
if (!safe.read) {
safe.read = seq;
} else if (safe.read !== seq) {
safe.read = true;
}
}
if (def.fixed == null) {
if (is_arguments(def)) return false;
if (def.global && def.name == "arguments") return false;
Expand Down Expand Up @@ -684,7 +693,7 @@ Compressor.prototype.compress = function(node) {
safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids;
}
if (def.fixed != null && safe.read) {
if (safe.read !== tw.safe_ids) return false;
if (safe.read !== tw.safe_ids.seq) return false;
if (tw.loop_ids[def.id] !== tw.in_loop) return false;
}
return safe_to_read(tw, def) && all(def.orig, function(sym) {
Expand Down Expand Up @@ -810,7 +819,7 @@ Compressor.prototype.compress = function(node) {
var scanner = new TreeWalker(function(node) {
if (node instanceof AST_DefaultValue) {
reset_flags(node);
push(tw);
push(tw, true);
node.value.walk(tw);
pop(tw);
var save = fixed;
Expand Down Expand Up @@ -899,14 +908,15 @@ Compressor.prototype.compress = function(node) {
var fn = this;
fn.inlined = false;
var iife = tw.parent();
var hit = is_async(fn) || is_generator(fn);
var sequential = !is_async(fn) && !is_generator(fn);
var hit = !sequential;
var aborts = false;
fn.walk(new TreeWalker(function(node) {
if (hit) return aborts = true;
if (node instanceof AST_Return) return hit = true;
if (node instanceof AST_Scope && node !== fn) return true;
}));
if (aborts) push(tw);
if (aborts) push(tw, sequential);
reset_variables(tw, compressor, fn);
// Virtually turn IIFE parameters into variable definitions:
// (function(a,b) {...})(c,d) ---> (function() {var a=c,b=d; ...})()
Expand Down Expand Up @@ -991,7 +1001,7 @@ Compressor.prototype.compress = function(node) {
return walk_lazy();
}
var safe = safe_to_read(tw, ld);
if (lazy) push(tw);
if (lazy) push(tw, true);
right.walk(tw);
if (lazy) pop(tw);
if (safe && !left.in_arg && safe_to_assign(tw, ld)) {
Expand Down Expand Up @@ -1073,7 +1083,7 @@ Compressor.prototype.compress = function(node) {
function walk_lazy() {
if (!lazy) return;
left.walk(tw);
push(tw);
push(tw, true);
right.walk(tw);
pop(tw);
return true;
Expand All @@ -1082,7 +1092,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Binary, function(tw) {
if (!lazy_op[this.operator]) return;
this.left.walk(tw);
push(tw);
push(tw, true);
this.right.walk(tw);
pop(tw);
return true;
Expand Down Expand Up @@ -1112,7 +1122,7 @@ Compressor.prototype.compress = function(node) {
}
exp.walk(tw);
var optional = node.optional;
if (optional) push(tw);
if (optional) push(tw, true);
node.args.forEach(function(arg) {
arg.walk(tw);
});
Expand Down Expand Up @@ -1182,27 +1192,27 @@ Compressor.prototype.compress = function(node) {
});
def(AST_ClassInitBlock, function(tw, descend, compressor) {
var node = this;
push(tw);
push(tw, true);
reset_variables(tw, compressor, node);
descend();
pop_scope(tw, node);
return true;
});
def(AST_Conditional, function(tw) {
this.condition.walk(tw);
push(tw);
push(tw, true);
this.consequent.walk(tw);
pop(tw);
push(tw);
push(tw, true);
this.alternative.walk(tw);
pop(tw);
return true;
});
def(AST_DefaultValue, function(tw) {
this.name.walk(tw);
push(tw);
push(tw, true);
this.value.walk(tw);
pop(tw);
this.name.walk(tw);
return true;
});
def(AST_Do, function(tw) {
Expand Down Expand Up @@ -1274,18 +1284,18 @@ Compressor.prototype.compress = function(node) {
});
def(AST_If, function(tw) {
this.condition.walk(tw);
push(tw);
push(tw, true);
this.body.walk(tw);
pop(tw);
if (this.alternative) {
push(tw);
push(tw, true);
this.alternative.walk(tw);
pop(tw);
}
return true;
});
def(AST_LabeledStatement, function(tw) {
push(tw);
push(tw, true);
this.body.walk(tw);
pop(tw);
return true;
Expand Down Expand Up @@ -1319,7 +1329,7 @@ Compressor.prototype.compress = function(node) {
def(AST_Sub, function(tw) {
if (!this.optional) return;
this.expression.walk(tw);
push(tw);
push(tw, true);
this.property.walk(tw);
pop(tw);
return true;
Expand All @@ -1334,15 +1344,15 @@ Compressor.prototype.compress = function(node) {
branch.expression.walk(tw);
if (first) {
first = false;
push(tw);
push(tw, true);
}
})
if (!first) pop(tw);
walk_body(node, tw);
return true;
});
def(AST_SwitchBranch, function(tw) {
push(tw);
push(tw, true);
walk_body(this, tw);
pop(tw);
return true;
Expand Down Expand Up @@ -1452,7 +1462,7 @@ Compressor.prototype.compress = function(node) {
node.globals.each(function(def) {
reset_def(tw, compressor, def);
});
push(tw);
push(tw, true);
reset_variables(tw, compressor, node);
descend();
pop_scope(tw, node);
Expand All @@ -1461,11 +1471,11 @@ Compressor.prototype.compress = function(node) {
def(AST_Try, function(tw, descend, compressor) {
var node = this;
reset_block_variables(tw, compressor, node);
push(tw);
push(tw, true);
walk_body(node, tw);
pop(tw);
if (node.bcatch) {
push(tw);
push(tw, true);
node.bcatch.walk(tw);
pop(tw);
}
Expand Down Expand Up @@ -1590,6 +1600,7 @@ Compressor.prototype.compress = function(node) {
// - `push()` & `pop()` when visiting conditional branches
// - backup & restore via `save_ids` when visiting out-of-order sections
tw.safe_ids = Object.create(null);
tw.safe_ids.seq = {};
this.walk(tw);
});

Expand Down Expand Up @@ -3524,6 +3535,7 @@ Compressor.prototype.compress = function(node) {
stat.alternative = make_node(AST_BlockStatement, stat, {
body: as_statement_array(stat.alternative).concat(extract_functions(merge_jump, jump)),
});
adjust_refs(ab.value, merge_jump);
statements[i] = stat;
statements[i] = stat.transform(compressor);
continue;
Expand Down Expand Up @@ -3563,6 +3575,7 @@ Compressor.prototype.compress = function(node) {
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
body: as_statement_array_with_return(stat.alternative, alt),
});
adjust_refs(alt.value, merge_jump);
statements[i] = stat;
statements[i] = stat.transform(compressor);
continue;
Expand Down Expand Up @@ -3776,6 +3789,37 @@ Compressor.prototype.compress = function(node) {
return body;
}

function adjust_refs(value, mode) {
if (!mode) return;
if (!value) return;
switch (mode) {
case 4:
return;
case 3:
case 2:
value = value.tail_node();
}
var fixed_by_id = new Dictionary();
value.walk(new TreeWalker(function(node) {
if (!(node instanceof AST_SymbolRef)) return;
var def = node.definition();
if (def.scope.resolve() !== scope) return;
var fixed = node.fixed;
if (!fixed || !fixed_by_id.has(def.id)) {
fixed_by_id.set(def.id, fixed);
} else if (fixed_by_id.get(def.id) !== fixed) {
fixed_by_id.set(def.id, false);
}
}));
if (fixed_by_id.size() > 0) jump.value.walk(new TreeWalker(function(node) {
if (!(node instanceof AST_SymbolRef)) return;
var def = node.definition();
var fixed = node.fixed;
if (!fixed || !fixed_by_id.has(def.id)) return;
if (fixed_by_id.get(def.id) !== fixed) node.fixed = false;
}));
}

function next_index(i) {
declare_only = true;
for (var j = i; ++j < statements.length;) {
Expand Down
5 changes: 2 additions & 3 deletions test/compress/collapse_vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -9321,12 +9321,11 @@ issue_4874: {
})(a = 42);
}
expect: {
var a;
null;
(function(b) {
for (var c in a && a[console.log("PASS")])
for (var c in 42, 42[console.log("PASS")])
console;
})(a = 42);
})();
}
expect_stdout: "PASS"
}
Expand Down
2 changes: 1 addition & 1 deletion test/compress/default-values.js
Original file line number Diff line number Diff line change
Expand Up @@ -2505,7 +2505,7 @@ issue_5463: {
var a, b, b;
console.log("PASS") && (
b = a = void 0,
b = [a = FAIL] = a && a
b = [a = FAIL] = a
);
}
expect_stdout: "PASS"
Expand Down
12 changes: 5 additions & 7 deletions test/compress/drop-unused.js
Original file line number Diff line number Diff line change
Expand Up @@ -1878,7 +1878,7 @@ issue_2846: {
var c = function(a, b) {
a = 0;
b && b(a);
return a++;
return +a;
}();
console.log(c);
}
Expand Down Expand Up @@ -2976,14 +2976,12 @@ issue_4025: {
console.log(a, b, d);
}
expect: {
var c = 0;
try {
console.log(c);
console.log(0);
} finally {
var d = c + 1;
c = 0;
0;
}
console.log(1, 1, d);
console.log(1, 1, 1);
}
expect_stdout: [
"0",
Expand Down Expand Up @@ -3696,7 +3694,7 @@ issue_5224: {
(function() {
var a = "FAIL 1";
null;
a = console.log(a);
console.log(a);
})(function() {
console.log(1 / 0);
a;
Expand Down
2 changes: 1 addition & 1 deletion test/compress/hoist_vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ issue_5411_2: {
var b, c;
b++;
b = "PASS",
c = c && c[b];
c;
console.log(b);
}
expect_stdout: "PASS"
Expand Down
27 changes: 27 additions & 0 deletions test/compress/if_return.js
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,33 @@ switch_return_5: {
]
}

merged_references: {
options = {
if_return: true,
reduce_vars: true,
unused: true,
}
input: {
var a, b = "PASS";
console.log(function(c) {
if (c = b)
return a || c;
c = FAIL;
return a || c;
}());
}
expect: {
var a, b = "PASS";
console.log(function(c) {
if (c = b);
else
c = FAIL;
return a || c;
}());
}
expect_stdout: "PASS"
}

issue_5583: {
options = {
conditionals: true,
Expand Down
7 changes: 4 additions & 3 deletions test/compress/reduce_vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -2488,7 +2488,7 @@ side_effects_assign: {
console.log(a);
}
expect: {
var a = typeof void (a && a.in);
var a = "undefined";
console.log(a);
}
expect_stdout: "undefined"
Expand Down Expand Up @@ -2530,7 +2530,8 @@ pure_getters_2: {
var a = a && a.b;
}
expect: {
var a = a && a.b;
var a;
a && a.b;
}
}

Expand Down Expand Up @@ -5424,7 +5425,7 @@ issue_2774: {
get a() {
var b;
(b = true) && b.c;
b = void 0;
void 0;
}
}.a);
}
Expand Down

0 comments on commit 10bc86b

Please sign in to comment.