enhance if_return & inline (#5538)

This commit is contained in:
Alex Lam S.L
2022-07-06 04:40:07 +01:00
committed by GitHub
parent aa2a9fbedb
commit 0207b46d70
6 changed files with 536 additions and 30 deletions

View File

@@ -1950,20 +1950,18 @@ Compressor.prototype.compress = function(node) {
return statements;
function last_of(compressor, predicate) {
var block = compressor.self(), level = 0;
var block = compressor.self(), level = 0, stat;
do {
if (block instanceof AST_Catch) {
block = compressor.parent(level++);
} else if (block instanceof AST_LabeledStatement) {
block = block.body;
}
var stat = null;
while (true) {
if (predicate(block)) return true;
block = compressor.parent(level++);
if (!(block instanceof AST_If)) break;
do {
stat = block;
}
if (predicate(stat)) return stat;
block = compressor.parent(level++);
} while (block instanceof AST_If);
} while (stat
&& (block instanceof AST_BlockStatement
|| block instanceof AST_Catch
@@ -3411,7 +3409,8 @@ Compressor.prototype.compress = function(node) {
var j = next_index(i);
var next = statements[j];
if (in_lambda && !next && stat instanceof AST_Return) {
if (in_lambda && !next && stat instanceof AST_Return
&& !(in_try && in_try.bfinally && in_async_generator(in_lambda))) {
if (!stat.value) {
changed = true;
statements.splice(i, 1);
@@ -3550,7 +3549,10 @@ Compressor.prototype.compress = function(node) {
if (stat instanceof AST_Exit) {
exit = stat;
exit_defs = null;
continue;
}
if (exit && exit === next) eliminate_returns(stat);
}
return changed;
@@ -3571,24 +3573,36 @@ Compressor.prototype.compress = function(node) {
});
}
function match_return(ab) {
if (!exit) return false;
if (exit.TYPE != ab.TYPE) return false;
var value = ab.value;
var equals = exit.equivalent_to(ab);
if (!equals && value instanceof AST_Sequence) {
value = value.tail_node();
equals = exit.value ? exit.value.equivalent_to(value) : is_undefined(value);
}
if (!equals) return false;
if (exit_defs == null) {
exit_defs = new Dictionary();
exit.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolRef) exit_defs.set(node.name, node.definition());
}));
if (!exit_defs.size()) exit_defs = false;
}
var abort = false;
if (value && exit_defs) value.walk(new TreeWalker(function(node) {
if (abort) return true;
if (node instanceof AST_SymbolRef && exit_defs.get(node.name) !== node.definition()) {
return abort = true;
}
}));
return !abort;
}
function can_drop_abort(ab) {
if (ab instanceof AST_Exit) {
if (exit && exit.equivalent_to(ab)) {
if (!exit_defs) {
exit_defs = new Dictionary();
exit.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolRef) exit_defs.set(node.name, node.definition());
}));
}
var abort = false;
ab.walk(new TreeWalker(function(node) {
if (abort) return true;
if (node instanceof AST_SymbolRef && exit_defs.get(node.name) !== node.definition()) {
return abort = true;
}
}));
if (!abort) return merge_exit = true;
}
if (match_return(ab)) return merge_exit = true;
return in_lambda && ab instanceof AST_Return && is_undefined(ab.value);
}
if (!(ab instanceof AST_LoopControl)) return false;
@@ -3640,6 +3654,15 @@ Compressor.prototype.compress = function(node) {
return tail;
}
function trim_return(value) {
if (!value) return;
if (exit.value) {
if (exit.value.TYPE == value.TYPE) return;
if (value instanceof AST_Sequence) return make_sequence(value, value.expressions.slice(0, -1));
}
return value;
}
function as_statement_array_with_return(node, ab) {
var body = as_statement_array(node);
var block = body, last;
@@ -3647,7 +3670,9 @@ Compressor.prototype.compress = function(node) {
block = last.body;
}
block.pop();
if (!merge_exit && ab.value) block.push(make_node(AST_SimpleStatement, ab.value, { body: ab.value }));
var value = ab.value;
if (merge_exit) value = trim_return(value);
if (value) block.push(make_node(AST_SimpleStatement, value, { body: value }));
return body;
}
@@ -3683,6 +3708,31 @@ Compressor.prototype.compress = function(node) {
if (var_defs.length > 0) args.push(make_node(AST_Var, stat, { definitions: var_defs }));
return args;
}
function eliminate_returns(stat, in_block) {
if (stat instanceof AST_Exit) {
if (match_return(stat)) {
var value = trim_return(stat.value);
if (value) return make_node(AST_SimpleStatement, value, { body: value });
return in_block ? null : make_node(AST_EmptyStatement, stat);
}
} else if (stat instanceof AST_If) {
stat.body = eliminate_returns(stat.body);
if (stat.alternative) stat.alternative = eliminate_returns(stat.alternative);
} else if (stat instanceof AST_LabeledStatement) {
stat.body = eliminate_returns(stat.body);
} else if (stat instanceof AST_Try) {
if (!stat.bfinally || !exit.value || exit.value.is_constant()) {
if (stat.bcatch) eliminate_returns(stat.bcatch);
var trimmed = eliminate_returns(stat.body.pop(), true);
if (trimmed) stat.body.push(trimmed);
}
} else if (stat instanceof AST_Block && !(stat instanceof AST_Scope || stat instanceof AST_Switch)) {
var trimmed = eliminate_returns(stat.body.pop(), true);
if (trimmed) stat.body.push(trimmed);
}
return stat;
}
}
function eliminate_dead_code(statements, compressor) {
@@ -10867,7 +10917,10 @@ Compressor.prototype.compress = function(node) {
append_var(decls, expressions, symbol);
if (value) expressions.push(value);
} else {
if (!value && in_loop && argname === name) value = make_node(AST_Undefined, self);
if (!value && argname === name && (in_loop
|| name.name == "arguments" && !is_arrow(fn) && is_arrow(scope))) {
value = make_node(AST_Undefined, self);
}
append_var(decls, expressions, symbol, value);
}
}