compress chained compound assignments (#2850)

This commit is contained in:
Alex Lam S.L
2018-01-29 15:13:25 +08:00
committed by GitHub
parent 4eb4cb656c
commit 6fa3fbeae8
3 changed files with 125 additions and 43 deletions

View File

@@ -320,6 +320,7 @@ merge(Compressor.prototype, {
function reset_def(compressor, def) { function reset_def(compressor, def) {
def.assignments = 0; def.assignments = 0;
def.chained = false;
def.direct_access = false; def.direct_access = false;
def.escaped = false; def.escaped = false;
if (def.scope.uses_eval || def.scope.uses_with) { if (def.scope.uses_eval || def.scope.uses_with) {
@@ -485,19 +486,27 @@ merge(Compressor.prototype, {
}); });
def(AST_Assign, function(tw) { def(AST_Assign, function(tw) {
var node = this; var node = this;
if (node.operator != "=" || !(node.left instanceof AST_SymbolRef)) return; if (!(node.left instanceof AST_SymbolRef)) return;
var d = node.left.definition(); var d = node.left.definition();
if (safe_to_assign(tw, d, node.right)) { var fixed = d.fixed;
d.references.push(node.left); if (!fixed && node.operator != "=") return;
d.assignments++; if (!safe_to_assign(tw, d, node.right)) return;
d.fixed = function() { d.references.push(node.left);
return node.right; d.assignments++;
}; if (node.operator != "=") d.chained = true;
mark(tw, d, false); d.fixed = node.operator == "=" ? function() {
node.right.walk(tw); return node.right;
mark(tw, d, true); } : function() {
return true; return make_node(AST_Binary, node, {
} operator: node.operator.slice(0, -1),
left: fixed instanceof AST_Node ? fixed : fixed(),
right: node.right
});
};
mark(tw, d, false);
node.right.walk(tw);
mark(tw, d, true);
return true;
}); });
def(AST_Binary, function(tw) { def(AST_Binary, function(tw) {
if (!lazy_op(this.operator)) return; if (!lazy_op(this.operator)) return;
@@ -672,6 +681,32 @@ merge(Compressor.prototype, {
if (this.bfinally) this.bfinally.walk(tw); if (this.bfinally) this.bfinally.walk(tw);
return true; return true;
}); });
def(AST_Unary, function(tw, descend) {
var node = this;
if (node.operator != "++" && node.operator != "--") return;
if (!(node.expression instanceof AST_SymbolRef)) return;
var d = node.expression.definition();
var fixed = d.fixed;
if (!fixed) return;
if (!safe_to_assign(tw, d, true)) return;
d.references.push(node.expression);
d.assignments++;
d.chained = true;
d.fixed = function() {
return make_node(AST_Binary, node, {
operator: node.operator.slice(0, -1),
left: make_node(AST_UnaryPrefix, node, {
operator: "+",
expression: fixed instanceof AST_Node ? fixed : fixed()
}),
right: make_node(AST_Number, node, {
value: 1
})
});
};
mark(tw, d, true);
return true;
});
def(AST_VarDef, function(tw, descend) { def(AST_VarDef, function(tw, descend) {
var node = this; var node = this;
var d = node.name.definition(); var d = node.name.definition();
@@ -2946,7 +2981,7 @@ merge(Compressor.prototype, {
if (def.value.has_side_effects(compressor)) { if (def.value.has_side_effects(compressor)) {
def.value.walk(tw); def.value.walk(tw);
} }
if (def.name.fixed_value() === def.value) { if (!node_def.chained && def.name.fixed_value() === def.value) {
fixed_ids[node_def.id] = def; fixed_ids[node_def.id] = def;
} }
} }
@@ -3164,7 +3199,7 @@ merge(Compressor.prototype, {
&& self.variables.get(sym.name) === (node_def = sym.definition())) { && self.variables.get(sym.name) === (node_def = sym.definition())) {
if (node instanceof AST_Assign) { if (node instanceof AST_Assign) {
node.right.walk(tw); node.right.walk(tw);
if (node.left.fixed_value() === node.right) { if (!node_def.chained && node.left.fixed_value() === node.right) {
fixed_ids[node_def.id] = node; fixed_ids[node_def.id] = node;
} }
} }

View File

@@ -52,13 +52,8 @@ collapse_vars_side_effects_1: {
console.log.bind(console)(s.charAt(i++), s.charAt(i++), s.charAt(i++), 7); console.log.bind(console)(s.charAt(i++), s.charAt(i++), s.charAt(i++), 7);
} }
function f2() { function f2() {
var log = console.log.bind(console), var s = "abcdef", i = 2;
s = "abcdef", console.log.bind(console)(s.charAt(i++), 5, s.charAt(i++), s.charAt(i++), 7);
i = 2,
x = s.charAt(i++),
y = s.charAt(i++),
z = s.charAt(i++);
log(x, i, y, z, 7);
} }
function f3() { function f3() {
var s = "abcdef", var s = "abcdef",
@@ -72,7 +67,7 @@ collapse_vars_side_effects_1: {
var i = 10, var i = 10,
x = i += 2, x = i += 2,
y = i += 3; y = i += 3;
console.log.bind(console)(x, i += 4, y, i); console.log.bind(console)(x, i += 4, y, 19);
} }
f1(), f2(), f3(), f4(); f1(), f2(), f3(), f4();
} }

View File

@@ -76,14 +76,12 @@ modified: {
console.log(a + 1); console.log(a + 1);
console.log(b + 1); console.log(b + 1);
} }
function f1() { function f1() {
var a = 1, b = 2; var a = 1, b = 2;
--b; --b;
console.log(a + 1); console.log(a + 1);
console.log(b + 1); console.log(b + 1);
} }
function f2() { function f2() {
var a = 1, b = 2, c = 3; var a = 1, b = 2, c = 3;
b = c; b = c;
@@ -92,7 +90,6 @@ modified: {
console.log(a + c); console.log(a + c);
console.log(a + b + c); console.log(a + b + c);
} }
function f3() { function f3() {
var a = 1, b = 2, c = 3; var a = 1, b = 2, c = 3;
b *= c; b *= c;
@@ -101,7 +98,6 @@ modified: {
console.log(a + c); console.log(a + c);
console.log(a + b + c); console.log(a + b + c);
} }
function f4() { function f4() {
var a = 1, b = 2, c = 3; var a = 1, b = 2, c = 3;
if (a) { if (a) {
@@ -114,28 +110,26 @@ modified: {
console.log(a + c); console.log(a + c);
console.log(a + b + c); console.log(a + b + c);
} }
function f5(a) { function f5(a) {
B = a; B = a;
console.log(A ? 'yes' : 'no'); console.log(typeof A ? "yes" : "no");
console.log(B ? 'yes' : 'no'); console.log(typeof B ? "yes" : "no");
} }
f0(), f1(), f2(), f3(), f4(), f5();
} }
expect: { expect: {
function f0() { function f0() {
var b = 2; var b = 2;
b++; b++;
console.log(2); console.log(2);
console.log(b + 1); console.log(4);
} }
function f1() { function f1() {
var b = 2; var b = 2;
--b; --b;
console.log(2); console.log(2);
console.log(b + 1); console.log(2);
} }
function f2() { function f2() {
3; 3;
console.log(4); console.log(4);
@@ -143,16 +137,14 @@ modified: {
console.log(4); console.log(4);
console.log(7); console.log(7);
} }
function f3() { function f3() {
var b = 2; var b = 2;
b *= 3; b *= 3;
console.log(1 + b); console.log(7);
console.log(b + 3); console.log(9);
console.log(4); console.log(4);
console.log(1 + b + 3); console.log(10);
} }
function f4() { function f4() {
var b = 2, c = 3; var b = 2, c = 3;
b = c; b = c;
@@ -161,13 +153,33 @@ modified: {
console.log(1 + c); console.log(1 + c);
console.log(1 + b + c); console.log(1 + b + c);
} }
function f5(a) { function f5(a) {
B = a; B = a;
console.log(A ? 'yes' : 'no'); console.log(typeof A ? "yes" : "no");
console.log(B ? 'yes' : 'no'); console.log(typeof B ? "yes" : "no");
} }
f0(), f1(), f2(), f3(), f4(), f5();
} }
expect_stdout: [
"2",
"4",
"2",
"2",
"4",
"6",
"4",
"7",
"7",
"9",
"4",
"10",
"4",
"6",
"4",
"7",
"yes",
"yes",
]
} }
unsafe_evaluate: { unsafe_evaluate: {
@@ -745,7 +757,7 @@ iife: {
expect: { expect: {
!function(a, b, c) { !function(a, b, c) {
b++; b++;
console.log(0, 1 * b, 5); console.log(0, 3, 5);
}(1, 2, 3); }(1, 2, 3);
} }
expect_stdout: true expect_stdout: true
@@ -766,7 +778,7 @@ iife_new: {
expect: { expect: {
var A = new function(a, b, c) { var A = new function(a, b, c) {
b++; b++;
console.log(0, 1 * b, 5); console.log(0, 3, 5);
}(1, 2, 3); }(1, 2, 3);
} }
expect_stdout: true expect_stdout: true
@@ -5383,3 +5395,43 @@ issue_2836: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
lvalues_def_1: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var b = 1;
var a = b++, b = NaN;
console.log(a, b);
}
expect: {
var b = 1;
var a = b++;
b = NaN;
console.log(a, b);
}
expect_stdout: "1 NaN"
}
lvalues_def_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var b = 1;
var a = b += 1, b = NaN;
console.log(a, b);
}
expect: {
var b = 1;
var a = b += 1;
b = NaN;
console.log(a, b);
}
expect_stdout: "2 NaN"
}