enhance inline (#3767)

This commit is contained in:
Alex Lam S.L
2020-04-10 03:48:24 +01:00
committed by GitHub
parent 41eb4f1725
commit b35f4c5a83
6 changed files with 144 additions and 60 deletions

View File

@@ -5819,38 +5819,45 @@ merge(Compressor.prototype, {
var args = self.args.concat(value || make_node(AST_Undefined, self));
return make_sequence(self, args).optimize(compressor);
}
var funarg, pos;
if (value instanceof AST_SymbolRef
&& (funarg = resolve_funarg(value.definition().orig))
&& (pos = fn.argnames.indexOf(funarg)) >= 0
&& (pos >= self.args.length - 1 || all(self.args.slice(pos), function(funarg) {
return !funarg.has_side_effects(compressor);
}))) {
var args = self.args.slice();
args.push(args.splice(pos, 1)[0] || make_node(AST_Undefined, self));
var node = make_sequence(self, args).optimize(compressor);
return maintain_this_binding(compressor, compressor.parent(), compressor.self(), node);
}
}
if (is_func) {
var def, value, scope, in_loop, level = -1;
var def, value;
if (can_inline
&& !fn.uses_arguments
&& !fn.pinned()
&& !(fn.name && fn instanceof AST_Function)
&& (value = can_flatten_body(stat))
&& (exp === fn
|| compressor.option("unused")
&& (def = exp.definition()).references.length == 1
&& !recursive_ref(compressor, def)
&& fn.is_constant_expression(exp.scope))
&& !self.pure
&& !fn.contains_this()
&& can_inject_symbols()) {
fn._squeezed = true;
if (exp !== fn) fn.parent_scope = exp.scope;
var node = make_sequence(self, flatten_fn()).optimize(compressor);
return maintain_this_binding(compressor, compressor.parent(), compressor.self(), node);
|| !recursive_ref(compressor, def = exp.definition) && fn.is_constant_expression(exp.scope))
&& !fn.contains_this()) {
if (can_substitute_directly()) {
var args = self.args.slice();
args.push(value.clone(true).transform(new TreeTransformer(function(node) {
if (node instanceof AST_SymbolRef) {
var def = node.definition();
if (fn.variables.get(node.name) !== def) return node;
var index = resolve_index(def);
var arg = args[index];
if (!arg) return make_node(AST_Undefined, self);
args[index] = null;
var parent = this.parent();
return parent ? maintain_this_binding(compressor, parent, node, arg) : arg;
}
})));
var node = make_sequence(self, args.filter(function(arg) {
return arg;
})).optimize(compressor);
node = maintain_this_binding(compressor, compressor.parent(), compressor.self(), node);
if (best_of(compressor, self, node) === node) return node;
}
var scope, in_loop, level = -1;
if ((exp === fn || compressor.option("unused") && exp.definition().references.length == 1)
&& can_inject_symbols()) {
fn._squeezed = true;
if (exp !== fn) fn.parent_scope = exp.scope;
var node = make_sequence(self, flatten_fn()).optimize(compressor);
return maintain_this_binding(compressor, compressor.parent(), compressor.self(), node);
}
}
if (compressor.option("side_effects")
&& all(fn.body, is_empty)
@@ -5877,14 +5884,6 @@ merge(Compressor.prototype, {
}
return try_evaluate(compressor, self);
function resolve_funarg(orig) {
var funarg;
for (var i = 0; orig[i] instanceof AST_SymbolFunarg; i++) {
funarg = orig[i];
}
return funarg;
}
function return_value(stat) {
if (!stat) return make_node(AST_Undefined, self);
if (stat instanceof AST_Return) {
@@ -5924,6 +5923,61 @@ merge(Compressor.prototype, {
return return_value(stat);
}
function resolve_index(def) {
for (var i = fn.argnames.length; --i >= 0;) {
if (fn.argnames[i].definition() === def) return i;
}
}
function can_substitute_directly() {
if (compressor.option("inline") <= 1 && fn.argnames.length) return;
if (fn.variables.size() > fn.argnames.length + 1) return;
if (!all(fn.argnames, function(argname) {
return argname.definition().references.length < 2;
})) return;
var abort = false;
var begin;
var in_order = [];
var side_effects = false;
value.walk(new TreeWalker(function(node) {
if (abort) return true;
if (node instanceof AST_Binary && lazy_op[node.operator]
|| node instanceof AST_Conditional) {
in_order = null;
return;
}
if (node instanceof AST_Scope) return abort = true;
var def;
if (node instanceof AST_SymbolRef && fn.variables.get(node.name) === (def = node.definition())) {
if (def.init instanceof AST_Defun) return abort = true;
if (is_lhs(node, this.parent())) return abort = true;
var index = resolve_index(def);
if (!(begin < index)) begin = index;
if (!in_order) return;
if (side_effects) {
in_order = null;
} else {
in_order.push(fn.argnames[index]);
}
return;
}
if (node.has_side_effects(compressor)) side_effects = true;
}));
if (abort) return;
var end = self.args.length;
if (in_order && fn.argnames.length >= end) {
end = fn.argnames.length;
while (end-- > begin && fn.argnames[end] === in_order.pop());
end++;
}
var scope = side_effects && compressor.find_parent(AST_Scope);
return end <= begin || all(self.args.slice(begin, end), side_effects ? function(funarg) {
return funarg.is_constant_expression(scope);
} : function(funarg) {
return !funarg.has_side_effects(compressor);
});
}
function var_exists(defined, name) {
return defined[name] || identifier_atom[name] || scope.var_names()[name];
}