enhance evaluate, functions & inline (#3931)

This commit is contained in:
Alex Lam S.L
2020-05-29 00:05:47 +01:00
committed by GitHub
parent d47ea77811
commit 6a5c63e1e3
4 changed files with 135 additions and 43 deletions

View File

@@ -450,6 +450,11 @@ merge(Compressor.prototype, {
tw.safe_ids[def.id] = safe; tw.safe_ids[def.id] = safe;
} }
function push_ref(def, ref) {
def.references.push(ref);
def.last_ref = ref;
}
function add_assign(tw, def, node) { function add_assign(tw, def, node) {
if (def.fixed === false) return; if (def.fixed === false) return;
tw.assigns.add(def.id, node); tw.assigns.add(def.id, node);
@@ -550,7 +555,7 @@ merge(Compressor.prototype, {
if (!(node instanceof AST_Symbol)) return; if (!(node instanceof AST_Symbol)) return;
var d = node.definition(); var d = node.definition();
if (!d) return; if (!d) return;
if (node instanceof AST_SymbolRef) d.references.push(node); if (node instanceof AST_SymbolRef) push_ref(d, node);
d.fixed = false; d.fixed = false;
}); });
def(AST_Accessor, function(tw, descend, compressor) { def(AST_Accessor, function(tw, descend, compressor) {
@@ -588,7 +593,7 @@ merge(Compressor.prototype, {
}); });
}; };
if (!safe) return; if (!safe) return;
d.references.push(sym); push_ref(d, sym);
mark(tw, d, false); mark(tw, d, false);
node.right.walk(tw); node.right.walk(tw);
mark(tw, d, true); mark(tw, d, true);
@@ -784,7 +789,7 @@ merge(Compressor.prototype, {
def(AST_SymbolRef, function(tw, descend, compressor) { def(AST_SymbolRef, function(tw, descend, compressor) {
if (this.fixed) delete this.fixed; if (this.fixed) delete this.fixed;
var d = this.definition(); var d = this.definition();
d.references.push(this); push_ref(d, this);
if (d.references.length == 1 if (d.references.length == 1
&& !d.fixed && !d.fixed
&& d.orig[0] instanceof AST_SymbolDefun) { && d.orig[0] instanceof AST_SymbolDefun) {
@@ -886,7 +891,7 @@ merge(Compressor.prototype, {
}); });
}; };
if (!safe) return; if (!safe) return;
d.references.push(exp); push_ref(d, exp);
mark(tw, d, true); mark(tw, d, true);
add_assign(tw, d, node); add_assign(tw, d, node);
return true; return true;
@@ -3280,12 +3285,30 @@ merge(Compressor.prototype, {
return this.value; return this.value;
}); });
def(AST_Assign, function(compressor, ignore_side_effects, cached, depth) { def(AST_Assign, function(compressor, ignore_side_effects, cached, depth) {
if (!ignore_side_effects) return this; var lhs = this.left;
if (this.operator != "=") return this; if (!ignore_side_effects) {
var node = this.right; if (!(lhs instanceof AST_SymbolRef)) return this;
if (!HOP(lhs, "_eval") && !lhs.fixed) return this;
var def = lhs.definition();
if (def.undeclared) return this;
if (def.last_ref !== lhs) return this;
if (def.single_use == "m") return this;
}
var op = this.operator;
var node;
if (HOP(lhs, "_eval") || !lhs.fixed) {
node = op == "=" ? this.right : make_node(AST_Binary, this, {
operator: op.slice(0, -1),
left: lhs,
right: this.right,
});
} else {
node = lhs;
}
var value = node._eval(compressor, ignore_side_effects, cached, depth); var value = node._eval(compressor, ignore_side_effects, cached, depth);
modified(this.left); if (value === node) return this;
return value === node ? this : value; modified(lhs);
return value;
}); });
def(AST_Sequence, function(compressor, ignore_side_effects, cached, depth) { def(AST_Sequence, function(compressor, ignore_side_effects, cached, depth) {
if (!ignore_side_effects) return this; if (!ignore_side_effects) return this;
@@ -3377,8 +3400,7 @@ merge(Compressor.prototype, {
case "++": case "++":
case "--": case "--":
if (!(e instanceof AST_SymbolRef)) return this; if (!(e instanceof AST_SymbolRef)) return this;
var refs = e.definition().references; if (!ignore_side_effects && e.definition().last_ref !== e) return this;
if (!ignore_side_effects && refs[refs.length - 1] !== e) return this;
if (HOP(e, "_eval")) v = +(op[0] + 1) + +v; if (HOP(e, "_eval")) v = +(op[0] + 1) + +v;
modified(e); modified(e);
return v; return v;
@@ -3388,11 +3410,11 @@ merge(Compressor.prototype, {
def(AST_UnaryPostfix, function(compressor, ignore_side_effects, cached, depth) { def(AST_UnaryPostfix, function(compressor, ignore_side_effects, cached, depth) {
var e = this.expression; var e = this.expression;
if (!e.fixed) return this; if (!e.fixed) return this;
var refs = e.definition().references; if (!ignore_side_effects && e.definition().last_ref !== e) return this;
if (!ignore_side_effects && refs[refs.length - 1] !== e) return this;
var v = e._eval(compressor, ignore_side_effects, cached, depth + 1); var v = e._eval(compressor, ignore_side_effects, cached, depth + 1);
if (v === e) return this;
modified(e); modified(e);
return v === e ? this : +v; return v;
}); });
var non_converting_binary = makePredicate("&& || === !=="); var non_converting_binary = makePredicate("&& || === !==");
def(AST_Binary, function(compressor, ignore_side_effects, cached, depth) { def(AST_Binary, function(compressor, ignore_side_effects, cached, depth) {
@@ -4385,13 +4407,11 @@ merge(Compressor.prototype, {
var defun = make_node(AST_Defun, def, def.value); var defun = make_node(AST_Defun, def, def.value);
defun.name = make_node(AST_SymbolDefun, def.name, def.name); defun.name = make_node(AST_SymbolDefun, def.name, def.name);
var name_def = def.name.scope.resolve().def_function(defun.name); var name_def = def.name.scope.resolve().def_function(defun.name);
if (old_def) def.value.walk(new TreeWalker(function(node) { if (old_def) old_def.references.forEach(function(node) {
if (node instanceof AST_SymbolRef && node.definition() === old_def) { node.name = name_def.name;
node.name = name_def.name; node.thedef = name_def;
node.thedef = name_def; node.reference({});
node.reference({}); });
}
}));
body.push(defun); body.push(defun);
} else { } else {
if (var_defs.length > 1 && sym.orig.indexOf(def.name) > sym.eliminated) { if (var_defs.length > 1 && sym.orig.indexOf(def.name) > sym.eliminated) {
@@ -6242,17 +6262,19 @@ merge(Compressor.prototype, {
&& !fn.uses_arguments && !fn.uses_arguments
&& !fn.pinned() && !fn.pinned()
&& !(fn.name && fn instanceof AST_Function) && !(fn.name && fn instanceof AST_Function)
&& (exp === fn && (exp === fn || !recursive_ref(compressor, def = exp.definition())
|| !recursive_ref(compressor, def = exp.definition()) && fn.is_constant_expression(exp.scope)) && fn.is_constant_expression(compressor.find_parent(AST_Scope)))
&& (value = can_flatten_body(stat)) && (value = can_flatten_body(stat))
&& !fn.contains_this()) { && !fn.contains_this()) {
var replacing = exp === fn || compressor.option("unused") && def.references.length - def.replaced == 1;
if (can_substitute_directly()) { if (can_substitute_directly()) {
var args = self.args.slice(); var args = self.args.slice();
var refs = [];
args.push(value.clone(true).transform(new TreeTransformer(function(node) { args.push(value.clone(true).transform(new TreeTransformer(function(node) {
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
var def = node.definition(); var def = node.definition();
if (fn.variables.get(node.name) !== def) { if (fn.variables.get(node.name) !== def) {
if (exp !== fn) def.references.push(node); refs.push(node);
return node; return node;
} }
var index = resolve_index(def); var index = resolve_index(def);
@@ -6267,11 +6289,17 @@ merge(Compressor.prototype, {
return arg; return arg;
})).optimize(compressor); })).optimize(compressor);
node = maintain_this_binding(compressor, compressor.parent(), compressor.self(), node); node = maintain_this_binding(compressor, compressor.parent(), compressor.self(), node);
if (best_of(compressor, self, node) === node) return node; if (replacing || best_of(compressor, self, node) === node) {
refs.forEach(function(ref) {
var def = ref.definition();
def.references.push(ref);
if (replacing) def.replaced++;
});
return node;
}
} }
var scope, in_loop, level = -1; var scope, in_loop, level = -1;
if ((exp === fn || compressor.option("unused") && def.references.length - def.replaced == 1) if (replacing && can_inject_symbols()) {
&& can_inject_symbols()) {
fn._squeezed = true; fn._squeezed = true;
if (exp !== fn) fn.parent_scope = exp.scope; if (exp !== fn) fn.parent_scope = exp.scope;
var node = make_sequence(self, flatten_fn()).optimize(compressor); var node = make_sequence(self, flatten_fn()).optimize(compressor);
@@ -6360,7 +6388,7 @@ merge(Compressor.prototype, {
var begin; var begin;
var in_order = []; var in_order = [];
var side_effects = false; var side_effects = false;
value.walk(new TreeWalker(function(node) { value.walk(new TreeWalker(function(node, descend) {
if (abort) return true; if (abort) return true;
if (node instanceof AST_Binary && lazy_op[node.operator] if (node instanceof AST_Binary && lazy_op[node.operator]
|| node instanceof AST_Conditional) { || node instanceof AST_Conditional) {
@@ -6386,7 +6414,11 @@ merge(Compressor.prototype, {
} }
return; return;
} }
if (node.has_side_effects(compressor)) side_effects = true; if (node.has_side_effects(compressor)) {
descend();
side_effects = true;
return true;
}
})); }));
if (abort) return; if (abort) return;
var end = self.args.length; var end = self.args.length;
@@ -6395,8 +6427,8 @@ merge(Compressor.prototype, {
while (end-- > begin && fn.argnames[end] === in_order.pop()); while (end-- > begin && fn.argnames[end] === in_order.pop());
end++; end++;
} }
var scope = side_effects && compressor.find_parent(AST_Scope); var scope = side_effects && !in_order && compressor.find_parent(AST_Scope);
return end <= begin || all(self.args.slice(begin, end), side_effects ? function(funarg) { return end <= begin || all(self.args.slice(begin, end), scope ? function(funarg) {
return funarg.is_constant_expression(scope); return funarg.is_constant_expression(scope);
} : function(funarg) { } : function(funarg) {
return !funarg.has_side_effects(compressor); return !funarg.has_side_effects(compressor);
@@ -6685,7 +6717,7 @@ merge(Compressor.prototype, {
var seq = lift_sequence_in_expression(self, compressor); var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor); if (seq !== self) return seq.optimize(compressor);
} }
return self; return try_evaluate(compressor, self);
}); });
var SIGN_OPS = makePredicate("+ -"); var SIGN_OPS = makePredicate("+ -");
@@ -7832,7 +7864,7 @@ merge(Compressor.prototype, {
expression: self.left expression: self.left
}); });
} }
return self; return try_evaluate(compressor, self);
function in_try(level, node) { function in_try(level, node) {
var right = self.right; var right = self.right;

View File

@@ -62,7 +62,7 @@ collapse_vars_side_effects_1: {
expect: { expect: {
function f1() { function f1() {
var s = "abcdef", i = 2; var s = "abcdef", i = 2;
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(4), 7);
} }
function f2() { function f2() {
var s = "abcdef", i = 2; var s = "abcdef", i = 2;
@@ -74,13 +74,14 @@ collapse_vars_side_effects_1: {
log = console.log.bind(console), log = console.log.bind(console),
x = s.charAt(i++), x = s.charAt(i++),
y = s.charAt(i++); y = s.charAt(i++);
log(x, s.charAt(i++), y, 7); log(x, s.charAt(4), y, 7);
} }
function f4() { function f4() {
var i = 10, var i = 10;
x = i += 2, i += 2,
y = i += 3; i += 3,
console.log.bind(console)(x, i += 4, y, 19); i += 4;
console.log.bind(console)(12, 19, 15, 19);
} }
f1(), f2(), f3(), f4(); f1(), f2(), f3(), f4();
} }

View File

@@ -2485,3 +2485,62 @@ issue_3920: {
} }
expect_stdout: "false" expect_stdout: "false"
} }
inlined_increment_prefix: {
options = {
evaluate: true,
inline: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0;
(function() {
++a;
})();
console.log(a += 0);
}
expect: {
var a = 0;
void ++a;
console.log(a += 0);
}
expect_stdout: "1"
}
inlined_increment_postfix: {
options = {
evaluate: true,
inline: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 0;
(function() {
a++;
})();
console.log(a += 0);
}
expect: {
var a = 0;
void a++;
console.log(a += 0);
}
expect_stdout: "1"
}
compound_assignment_to_property: {
options = {
evaluate: true,
unsafe: true,
}
input: {
1 + (0..p >>= 0) && console.log("PASS");
}
expect: {
1 + (0..p >>= 0),
console.log("PASS");
}
expect_stdout: "PASS"
}

View File

@@ -2724,8 +2724,8 @@ issue_1814_1: {
expect: { expect: {
!function() { !function() {
!function(a) { !function(a) {
console.log(a++, 42); console.log(0, 42);
}(0); }();
}(); }();
} }
expect_stdout: "0 42" expect_stdout: "0 42"
@@ -2751,8 +2751,8 @@ issue_1814_2: {
expect: { expect: {
!function() { !function() {
!function(a) { !function(a) {
console.log("321", a++); console.log("321", 0);
}(0); }();
}(); }();
} }
expect_stdout: "321 0" expect_stdout: "321 0"