Skip to content

Commit

Permalink
fix(es/minifier): calc function body cost when inline function
Browse files Browse the repository at this point in the history
  • Loading branch information
Austaras committed Jul 29, 2022
1 parent 328e812 commit fc8c9b6
Show file tree
Hide file tree
Showing 23 changed files with 1,137 additions and 1,291 deletions.
2 changes: 1 addition & 1 deletion crates/swc_ecma_minifier/src/analyzer/mod.rs
Expand Up @@ -114,7 +114,7 @@ pub(crate) struct VarUsageInfo {

pub no_side_effect_for_member_access: bool,

pub used_as_callee: bool,
pub callee_count: usize,

pub used_as_arg: bool,

Expand Down
4 changes: 2 additions & 2 deletions crates/swc_ecma_minifier/src/analyzer/storage/normal.rs
Expand Up @@ -70,7 +70,7 @@ impl Storage for ProgramData {
e.get_mut().no_side_effect_for_member_access
&& var_info.no_side_effect_for_member_access;

e.get_mut().used_as_callee |= var_info.used_as_callee;
e.get_mut().callee_count += var_info.callee_count;
e.get_mut().used_as_arg |= var_info.used_as_arg;

e.get_mut().pure_fn |= var_info.pure_fn;
Expand Down Expand Up @@ -247,7 +247,7 @@ impl VarDataLike for VarUsageInfo {
}

fn mark_used_as_callee(&mut self) {
self.used_as_callee = true;
self.callee_count += 1;
}

fn mark_used_as_arg(&mut self) {
Expand Down
2 changes: 1 addition & 1 deletion crates/swc_ecma_minifier/src/compress/optimize/iife.rs
Expand Up @@ -659,7 +659,7 @@ where
self.data
.vars
.get(id)
.map(|usage| usage.ref_count == 1 && usage.used_as_callee)
.map(|usage| usage.ref_count == 1 && usage.callee_count > 0)
.unwrap_or(false)
}) {
return true;
Expand Down
51 changes: 32 additions & 19 deletions crates/swc_ecma_minifier/src/compress/optimize/inline.rs
Expand Up @@ -5,6 +5,7 @@ use swc_ecma_utils::{find_pat_ids, ExprExt, IdentUsageFinder};

use super::Optimizer;
use crate::{
analyzer::VarUsageInfo,
compress::optimize::util::{class_has_side_effect, is_valid_for_lhs},
mode::Mode,
util::{
Expand Down Expand Up @@ -311,7 +312,7 @@ where
}
}

if !usage.used_as_callee {
if usage.callee_count == 0 {
if let Expr::Fn(..) | Expr::Arrow(..) = &**init {
return;
}
Expand Down Expand Up @@ -365,8 +366,21 @@ where
}

/// Check if the body of a function is simple enough to inline.
fn is_fn_body_simple_enough_to_inline(&self, body: &BlockStmt, param_count: usize) -> bool {
let cost_limit = 3 + param_count * 2;
fn is_fn_body_simple_enough_to_inline(
&self,
body: &BlockStmt,
param_count: usize,
usage: &VarUsageInfo,
) -> bool {
let param_cost = param_count * 2;
// if it's passed as value but not called, the function expr cannot be removed
let func_body_cost = if usage.ref_count == usage.callee_count {
// length of "function c(){}"
14 / usage.usage_count
} else {
0
};
let cost_limit = 3 + param_cost + func_body_cost;

if body.stmts.len() == 1 {
match &body.stmts[0] {
Expand Down Expand Up @@ -490,6 +504,10 @@ where
return;
}

if usage.ref_count == 0 {
return;
}

// Inline very simple functions.
match decl {
Decl::Fn(f) if self.options.inline >= 2 && f.ident.sym != *"arguments" => {
Expand All @@ -501,32 +519,27 @@ where
&& self.is_fn_body_simple_enough_to_inline(
body,
f.function.params.len(),
usage,
)
{
if f.function.params.iter().any(|param| {
matches!(param.pat, Pat::Rest(..) | Pat::Assign(..))
}) {
return;
}
trace_op!(
"inline: Decided to inline function '{}{:?}' as it's very \
simple",
f.ident.sym,
f.ident.span.ctxt
);

if f.function.params.iter().any(|param| {
matches!(param.pat, Pat::Rest(..) | Pat::Assign(..))
}) {
return;
}

self.vars.simple_functions.insert(
i.to_id(),
match decl {
Decl::Fn(f) => Box::new(Expr::Fn(FnExpr {
ident: None,
function: f.function.clone(),
})),
_ => {
unreachable!()
}
},
Box::new(Expr::Fn(FnExpr {
ident: None,
function: f.function.clone(),
})),
);
return;
}
Expand All @@ -548,7 +561,7 @@ where
//
if (self.options.reduce_vars || self.options.collapse_vars || self.options.inline != 0)
&& usage.ref_count == 1
&& (usage.is_fn_local || (usage.used_as_callee && !usage.used_above_decl))
&& (usage.is_fn_local || (usage.callee_count > 0 && !usage.used_above_decl))
&& !usage.executed_multiple_time
&& !usage.inline_prevented
&& (match decl {
Expand Down
16 changes: 6 additions & 10 deletions crates/swc_ecma_minifier/tests/fixture/issues/2257/full/output.js
Expand Up @@ -10152,9 +10152,6 @@
function escapeGroup(group) {
return group.replace(/([=!:$\/()])/g, "\\$1");
}
function attachKeys(re, keys) {
return re.keys = keys, re;
}
function flags(options) {
return options && options.sensitive ? "" : "i";
}
Expand All @@ -10168,13 +10165,13 @@
keys.push(token), token.repeat && (capture += "(?:" + prefix + capture + ")*"), route += capture = token.optional ? token.partial ? prefix + "(" + capture + ")?" : "(?:" + prefix + "(" + capture + "))?" : prefix + "(" + capture + ")";
}
}
var delimiter = escapeString(options.delimiter || "/"), endsWithDelimiter = route.slice(-delimiter.length) === delimiter;
return strict || (route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + "(?:" + delimiter + "(?=$))?"), end ? route += "$" : route += strict && endsWithDelimiter ? "" : "(?=" + delimiter + "|$)", attachKeys(RegExp("^" + route, flags(options)), keys);
var re, keys1, delimiter = escapeString(options.delimiter || "/"), endsWithDelimiter = route.slice(-delimiter.length) === delimiter;
return strict || (route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + "(?:" + delimiter + "(?=$))?"), end ? route += "$" : route += strict && endsWithDelimiter ? "" : "(?=" + delimiter + "|$)", re = RegExp("^" + route, flags(options)), keys1 = keys, re.keys = keys1, re;
}
function pathToRegexp(path, keys, options) {
var path1, keys1, options1;
return (isarray(keys) || (options = keys || options, keys = []), options = options || {}, path instanceof RegExp) ? function(path, keys) {
var groups = path.source.match(/\((?!\?)/g);
var re, keys1, groups = path.source.match(/\((?!\?)/g);
if (groups) for(var i = 0; i < groups.length; i++)keys.push({
name: i,
prefix: null,
Expand All @@ -10185,11 +10182,10 @@
asterisk: !1,
pattern: null
});
return attachKeys(path, keys);
return re = path, keys1 = keys, re.keys = keys1, re;
}(path, keys) : isarray(path) ? function(path, keys, options) {
for(var parts = [], i = 0; i < path.length; i++)parts.push(pathToRegexp(path[i], keys, options).source);
var regexp = RegExp("(?:" + parts.join("|") + ")", flags(options));
return attachKeys(regexp, keys);
for(var re, keys1, parts = [], i = 0; i < path.length; i++)parts.push(pathToRegexp(path[i], keys, options).source);
return re = RegExp("(?:" + parts.join("|") + ")", flags(options)), keys1 = keys, re.keys = keys1, re;
}(path, keys, options) : (path1 = path, keys1 = keys, tokensToRegExp(parse(path1, options1 = options), keys1, options1));
}
},
Expand Down
Expand Up @@ -43,15 +43,9 @@
}), this.tags = [], this.ctr = 0;
}, StyleSheet;
}(), abs = Math.abs, Utility_from = String.fromCharCode;
function trim(value) {
return value.trim();
}
function replace(value, pattern, replacement) {
return value.replace(pattern, replacement);
}
function indexof(value, search) {
return value.indexOf(search);
}
function Utility_charat(value, index) {
return 0 | value.charCodeAt(index);
}
Expand All @@ -61,9 +55,6 @@
function Utility_strlen(value) {
return value.length;
}
function Utility_sizeof(value) {
return value.length;
}
function Utility_append(value, array) {
return array.push(value), value;
}
Expand Down Expand Up @@ -94,9 +85,6 @@
function peek() {
return Utility_charat(characters, position);
}
function slice(begin, end) {
return Utility_substr(characters, begin, end);
}
function token(type) {
switch(type){
case 0:
Expand Down Expand Up @@ -132,20 +120,18 @@
function alloc(value) {
return line = column = 1, Tokenizer_length = Utility_strlen(characters = value), position = 0, [];
}
function dealloc(value) {
return characters = "", value;
}
function delimit(type) {
return trim(slice(position - 1, delimiter(91 === type ? type + 2 : 40 === type ? type + 1 : type)));
var begin, end;
return (begin = position - 1, end = delimiter(91 === type ? type + 2 : 40 === type ? type + 1 : type), Utility_substr(characters, begin, end)).trim();
}
function whitespace(type) {
for(; character = peek();)if (character < 33) next();
else break;
return token(type) > 2 || token(character) > 3 ? "" : " ";
}
function escaping(index, count) {
for(; --count && next() && !(character < 48) && !(character > 102) && (!(character > 57) || !(character < 65)) && (!(character > 70) || !(character < 97)););
return slice(index, position + (count < 6 && 32 == peek() && 32 == next()));
for(var begin, end; --count && next() && !(character < 48) && !(character > 102) && (!(character > 57) || !(character < 65)) && (!(character > 70) || !(character < 97)););
return begin = index, end = position + (count < 6 && 32 == peek() && 32 == next()), Utility_substr(characters, begin, end);
}
function delimiter(type) {
for(; next();)switch(character){
Expand All @@ -165,15 +151,15 @@
function commenter(type, index) {
for(; next();)if (type + character === 57) break;
else if (type + character === 84 && 47 === peek()) break;
return "/*" + slice(index, position - 1) + "*" + Utility_from(47 === type ? type : next());
return "/*" + Utility_substr(characters, index, position - 1) + "*" + Utility_from(47 === type ? type : next());
}
function identifier(index) {
for(; !token(peek());)next();
return slice(index, position);
return Utility_substr(characters, index, position);
}
var MS = "-ms-", MOZ = "-moz-", WEBKIT = "-webkit-", COMMENT = "comm", Enum_RULESET = "rule", DECLARATION = "decl";
function serialize(children, callback) {
for(var output = "", length = Utility_sizeof(children), i = 0; i < length; i++)output += callback(children[i], i, children, callback) || "";
for(var output = "", length = children.length, i = 0; i < length; i++)output += callback(children[i], i, children, callback) || "";
return output;
}
function stringify(element, index, children, callback) {
Expand All @@ -189,7 +175,7 @@
return Utility_strlen(children = serialize(element.children, callback)) ? element.return = element.value + "{" + children + "}" : "";
}
function prefix(value, length) {
var value1;
var value1, search, search1;
switch((((length << 2 ^ Utility_charat(value1 = value, 0)) << 2 ^ Utility_charat(value1, 1)) << 2 ^ Utility_charat(value1, 2)) << 2 ^ Utility_charat(value1, 3)){
case 5103:
return WEBKIT + "print-" + value + value;
Expand Down Expand Up @@ -274,13 +260,13 @@
case 102:
return replace(value, /(.+:)(.+)-([^]+)/, "$1" + WEBKIT + "$2-$3$1" + MOZ + (108 == Utility_charat(value, length + 3) ? "$3" : "$2-$3")) + value;
case 115:
return ~indexof(value, "stretch") ? prefix(replace(value, "stretch", "fill-available"), length) + value : value;
return ~(search = "stretch", value.indexOf(search)) ? prefix(replace(value, "stretch", "fill-available"), length) + value : value;
}
break;
case 4949:
if (115 !== Utility_charat(value, length + 1)) break;
case 6444:
switch(Utility_charat(value, Utility_strlen(value) - 3 - (~indexof(value, "!important") && 10))){
switch(Utility_charat(value, Utility_strlen(value) - 3 - (~(search1 = "!important", value.indexOf(search1)) && 10))){
case 107:
return replace(value, ":", ":" + WEBKIT) + value;
case 101:
Expand Down Expand Up @@ -385,7 +371,7 @@
function ruleset(value, root, parent, index, offset, rules, points, type, props, children, length) {
for(var post = offset - 1, rule = 0 === offset ? rules : [
""
], size = Utility_sizeof(rule), i = 0, j = 0, k = 0; i < index; ++i)for(var x = 0, y = Utility_substr(value, post + 1, post = abs(j = points[i])), z = value; x < size; ++x)(z = trim(j > 0 ? rule[x] + " " + y : replace(y, /&\f/g, rule[x]))) && (props[k++] = z);
], size = rule.length, i = 0, j = 0, k = 0; i < index; ++i)for(var x = 0, y = Utility_substr(value, post + 1, post = abs(j = points[i])), z = value; x < size; ++x)(z = (j > 0 ? rule[x] + " " + y : replace(y, /&\f/g, rule[x])).trim()) && (props[k++] = z);
return node(value, root, parent, 0 === offset ? Enum_RULESET : type, props, children, length);
}
function comment(value, root, parent) {
Expand All @@ -396,7 +382,7 @@
}
var identifierWithPointTracking = function(begin, points, index) {
for(var previous = 0, character = 0; previous = character, character = peek(), 38 === previous && 12 === character && (points[index] = 1), !token(character);)next();
return slice(begin, position);
return Utility_substr(characters, begin, position);
}, toRules = function(parsed, points) {
var index = -1, character = 44;
do switch(token(character)){
Expand All @@ -416,12 +402,15 @@
}
while (character = next())
return parsed;
}, getRules = function(value, points) {
var value1;
return value1 = toRules(alloc(value), points), characters = "", value1;
}, fixedElements = new WeakMap(), compat = function(element) {
if ("rule" === element.type && element.parent && element.length) {
for(var value = element.value, parent = element.parent, isImplicitRule = element.column === parent.column && element.line === parent.line; "rule" !== parent.type;)if (!(parent = parent.parent)) return;
if ((1 !== element.props.length || 58 === value.charCodeAt(0) || fixedElements.get(parent)) && !isImplicitRule) {
fixedElements.set(element, !0);
for(var value1, points, points1 = [], rules = (value1 = value, points = points1, dealloc(toRules(alloc(value1), points))), parentRules = parent.props, i = 0, k = 0; i < rules.length; i++)for(var j = 0; j < parentRules.length; j++, k++)element.props[k] = points1[i] ? rules[i].replace(/&\f/g, parentRules[j]) : parentRules[j] + " " + rules[i];
for(var points = [], rules = getRules(value, points), parentRules = parent.props, i = 0, k = 0; i < rules.length; i++)for(var j = 0; j < parentRules.length; j++, k++)element.props[k] = points[i] ? rules[i].replace(/&\f/g, parentRules[j]) : parentRules[j] + " " + rules[i];
}
}
}, removeLabel = function(element) {
Expand Down Expand Up @@ -632,19 +621,19 @@
}(function(rule) {
currentSheet.insert(rule);
}),
], serializer = (collection = [
], serializer = (length = (collection = [
compat,
removeLabel
].concat(stylisPlugins, finalizingPlugins), length = Utility_sizeof(collection), function(element, index, children, callback) {
].concat(stylisPlugins, finalizingPlugins)).length, function(element, index, children, callback) {
for(var output = "", i = 0; i < length; i++)output += collection[i](element, index, children, callback) || "";
return output;
}), stylis = function(styles) {
var value;
return serialize(dealloc(parse("", null, null, null, [
var value, value1;
return serialize((value1 = parse("", null, null, null, [
""
], value = alloc(value = styles), 0, [
0
], value)), serializer);
], value), characters = "", value1), serializer);
};
_insert = function(selector, serialized, sheet, shouldCache) {
currentSheet = sheet, stylis(selector ? selector + "{" + serialized.styles + "}" : serialized.styles), shouldCache && (cache.inserted[serialized.name] = !0);
Expand Down
Expand Up @@ -20,12 +20,9 @@
default:
return source;
}
for(const prop in source)source.hasOwnProperty(prop) && isValidKey(prop) && (target[prop] = deepExtend(target[prop], source[prop]));
for(const prop in source)source.hasOwnProperty(prop) && "__proto__" !== prop && (target[prop] = deepExtend(target[prop], source[prop]));
return target;
}
function isValidKey(key) {
return "__proto__" !== key;
}
function getUA() {
return "undefined" != typeof navigator && "string" == typeof navigator.userAgent ? navigator.userAgent : "";
}
Expand Down

0 comments on commit fc8c9b6

Please sign in to comment.