Skip to content

Commit

Permalink
feat(es/minifier): Ignore return value if a param of IIFE is not used (
Browse files Browse the repository at this point in the history
  • Loading branch information
kdy1 committed Oct 14, 2022
1 parent e46a192 commit d334c6e
Show file tree
Hide file tree
Showing 20 changed files with 180 additions and 85 deletions.
@@ -1,2 +1,2 @@
//// [emitDefaultParametersFunctionExpressionES6.ts]
!function(num, boo = !1, ...rest) {}(10);
!function(num, boo = !1, ...rest) {}(0);
Expand Up @@ -119,7 +119,7 @@ export var M = function(_superClass) {
return _class_call_check(this, M), _this.prop = 12, _possible_constructor_return(_this);
}
return _inherits(M, null), _create_super(M), M;
}(null);
}(0);
export var N = function(L) {
"use strict";
_inherits(N, L);
Expand Down Expand Up @@ -148,7 +148,7 @@ export var VariableBase = function(x) {
return _class_call_check(this, VariableBase), _super.apply(this, arguments);
}
return VariableBase;
}(null);
}(0);
export var HasStatics = function() {
"use strict";
function HasStatics() {
Expand Down
Expand Up @@ -21,4 +21,4 @@ var aa = [
aa = function(a, x) {
var result = a.slice();
return result.push(1), result;
}(aa, 1);
}(aa, 0);
146 changes: 119 additions & 27 deletions crates/swc_ecma_minifier/src/compress/optimize/iife.rs
Expand Up @@ -157,21 +157,6 @@ where
Callee::Expr(e) => &mut **e,
};

fn find_params(callee: &mut Expr) -> Option<Vec<&mut Pat>> {
match callee {
Expr::Arrow(callee) => Some(callee.params.iter_mut().collect()),
Expr::Fn(callee) => Some(
callee
.function
.params
.iter_mut()
.map(|param| &mut param.pat)
.collect(),
),
_ => None,
}
}

fn clean_params(callee: &mut Expr) {
match callee {
Expr::Arrow(callee) => callee.params.retain(|p| !p.is_invalid()),
Expand All @@ -195,17 +180,6 @@ where
}
}

fn find_body(callee: &mut Expr) -> Option<Either<&mut BlockStmt, &mut Expr>> {
match callee {
Expr::Arrow(e) => match &mut e.body {
BlockStmtOrExpr::BlockStmt(b) => Some(Either::Left(b)),
BlockStmtOrExpr::Expr(b) => Some(Either::Right(&mut **b)),
},
Expr::Fn(e) => Some(Either::Left(e.function.body.as_mut().unwrap())),
_ => None,
}
}

let params = find_params(callee);
if let Some(mut params) = params {
let mut vars = HashMap::default();
Expand Down Expand Up @@ -315,13 +289,106 @@ where
trace_op!("inline: Inlining arguments");
optimizer.inline_vars_in_node(body, vars);
}
_ => {}
_ => {
unreachable!("find_body and find_params should match")
}
}
}

clean_params(callee);
}

/// If a parameter is not used, we can ignore return value of the
/// corresponding argument.
pub(super) fn ignore_unused_args_of_iife(&mut self, e: &mut CallExpr) {
if !self.options.unused {
return;
}

let callee = match &mut e.callee {
Callee::Super(_) | Callee::Import(_) => return,
Callee::Expr(e) => &mut **e,
};

match find_body(callee) {
Some(body) => match body {
Either::Left(body) => {
if contains_arguments(body) {
return;
}
}
Either::Right(body) => {
if contains_arguments(body) {
return;
}
}
},
None => return,
}

if let Expr::Fn(FnExpr {
ident: Some(ident), ..
}) = callee
{
if self
.data
.vars
.get(&ident.to_id())
.filter(|usage| usage.used_recursively)
.is_some()
{
return;
}
}

let mut removed = vec![];
let params = find_params(callee);
if let Some(mut params) = params {
// We check for parameter and argument
for (idx, param) in params.iter_mut().enumerate() {
if let Pat::Ident(param) = &mut **param {
if let Some(usage) = self.data.vars.get(&param.to_id()) {
if usage.ref_count == 0 {
removed.push(idx);
}
}
}
}

if removed.is_empty() {
log_abort!("`removed` is empty");
return;
}
} else {
unreachable!("find_body and find_params should match")
}

for idx in removed {
if let Some(arg) = e.args.get_mut(idx) {
if arg.spread.is_some() {
break;
}

// Optimize
let new = self.ignore_return_value(&mut arg.expr);

if let Some(new) = new {
arg.expr = Box::new(new);
} else {
// Use `0` if it's removed.
arg.expr = Number {
span: arg.expr.span(),
value: 0.0,
raw: None,
}
.into();
}
} else {
break;
}
}
}

#[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
pub(super) fn inline_vars_in_node<N>(&mut self, n: &mut N, mut vars: FxHashMap<Id, Box<Expr>>)
where
Expand Down Expand Up @@ -1014,3 +1081,28 @@ where
}
}
}

fn find_params(callee: &mut Expr) -> Option<Vec<&mut Pat>> {
match callee {
Expr::Arrow(callee) => Some(callee.params.iter_mut().collect()),
Expr::Fn(callee) => Some(
callee
.function
.params
.iter_mut()
.map(|param| &mut param.pat)
.collect(),
),
_ => None,
}
}
fn find_body(callee: &mut Expr) -> Option<Either<&mut BlockStmt, &mut Expr>> {
match callee {
Expr::Arrow(e) => match &mut e.body {
BlockStmtOrExpr::BlockStmt(b) => Some(Either::Left(b)),
BlockStmtOrExpr::Expr(b) => Some(Either::Right(&mut **b)),
},
Expr::Fn(e) => Some(Either::Left(e.function.body.as_mut().unwrap())),
_ => None,
}
}
4 changes: 3 additions & 1 deletion crates/swc_ecma_minifier/src/compress/optimize/mod.rs
Expand Up @@ -623,7 +623,8 @@ where
"ignore_return_value: Dropping unused expr: {}",
dump(&*e, false)
);
self.changed = true;
// We don't need to run this again
// self.changed = true;
return None;
}

Expand Down Expand Up @@ -1575,6 +1576,7 @@ where
e.args.visit_mut_with(&mut *self.with_ctx(ctx));
}

self.ignore_unused_args_of_iife(e);
self.inline_args_of_iife(e);
}

Expand Down
26 changes: 13 additions & 13 deletions crates/swc_ecma_minifier/tests/benches-full/echarts.js
Expand Up @@ -5959,7 +5959,7 @@
state.z2 = el.z2 + (null != z2EmphasisLift ? z2EmphasisLift : 10);
}
return state;
}(this, stateName, targetStates, state1);
}(this, 0, targetStates, state1);
if ('blur' === stateName) return state = state1, hasBlur = indexOf(this.currentStates, stateName) >= 0, currentOpacity = this.style.opacity, fromState = hasBlur ? null : function(el, props, toStateName, defaultValue) {
for(var style = el.style, fromState = {}, i = 0; i < props.length; i++){
var propName = props[i], val = style[propName];
Expand All @@ -5984,7 +5984,7 @@
state.z2 = el.z2 + (null != z2SelectLift ? z2SelectLift : 9);
}
return state;
}(this, stateName, state1);
}(this, 0, state1);
}
return state1;
}
Expand Down Expand Up @@ -15449,7 +15449,7 @@
for(var i = 0; i < lastLevelTicks.length - 1; i++){
var approxInterval1, approxInterval2, approxInterval3, startTick = lastLevelTicks[i].value, endTick = lastLevelTicks[i + 1].value;
if (startTick !== endTick) {
var interval = void 0, getterName = void 0, setterName = void 0, isDate = !1;
var interval = void 0, getterName = void 0, setterName = void 0;
switch(unitName){
case 'year':
interval = Math.max(1, Math.round(approxInterval / 86400000 / 365)), getterName = fullYearGetterName(isUTC), setterName = isUTC ? 'setUTCFullYear' : 'setFullYear';
Expand All @@ -15462,7 +15462,7 @@
case 'week':
case 'half-week':
case 'day':
approxInterval2 = approxInterval, interval = (approxInterval2 /= 86400000) > 16 ? 16 : approxInterval2 > 7.5 ? 7 : approxInterval2 > 3.5 ? 4 : approxInterval2 > 1.5 ? 2 : 1, getterName = dateGetterName(isUTC), setterName = dateSetterName(isUTC), isDate = !0;
approxInterval2 = approxInterval, interval = (approxInterval2 /= 86400000) > 16 ? 16 : approxInterval2 > 7.5 ? 7 : approxInterval2 > 3.5 ? 4 : approxInterval2 > 1.5 ? 2 : 1, getterName = dateGetterName(isUTC), setterName = dateSetterName(isUTC);
break;
case 'half-day':
case 'quarter-day':
Expand All @@ -15486,7 +15486,7 @@
value: dateTime,
notAdd: !0
});
})(interval, startTick, endTick, getterName, setterName, isDate, newAddedTicks), 'year' === unitName && levelTicks.length > 1 && 0 === i && levelTicks.unshift({
})(interval, startTick, endTick, getterName, setterName, 0, newAddedTicks), 'year' === unitName && levelTicks.length > 1 && 0 === i && levelTicks.unshift({
value: levelTicks[0].value - interval
});
}
Expand Down Expand Up @@ -23738,7 +23738,7 @@
return inner$8(mapping).drColorMappingBy = colorMappingBy, mapping;
}
}
}(node, nodeModel, nodeLayout, nodeItemStyleModel, visuals1, viewChildren);
}(0, nodeModel, nodeLayout, 0, visuals1, viewChildren);
each(viewChildren, function(child, index) {
if (child.depth >= viewRootAncestors.length || child === viewRootAncestors[child.depth]) {
var childVisual = function(nodeModel, visuals, child, index, mapping, seriesModel) {
Expand Down Expand Up @@ -27474,7 +27474,7 @@
depth: maxDepth
}, !0);
});
}(nodes, nodeAlign, orient, maxDepth), kx = 'vertical' === orient ? (height - nodeWidth) / maxDepth : (width - nodeWidth) / maxDepth, each(nodes, function(node) {
}(nodes, nodeAlign, 0, maxDepth), kx = 'vertical' === orient ? (height - nodeWidth) / maxDepth : (width - nodeWidth) / maxDepth, each(nodes, function(node) {
var nodeDepth = node.getLayout().depth * kx;
'vertical' === orient ? node.setLayout({
y: nodeDepth
Expand Down Expand Up @@ -29254,7 +29254,7 @@
barRectShape[valueDim.wh] = pxSign * Math.max(Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix)), barRectShape[categoryDim.wh] = layout[categoryDim.wh];
var clipShape = outputSymbolMeta.clipShape = {};
clipShape[categoryDim.xy] = -layout[categoryDim.xy], clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh], clipShape[valueDim.xy] = 0, clipShape[valueDim.wh] = layout[valueDim.wh];
}(itemModel, symbolSize1, layout, symbolRepeat, symbolClip, symbolOffset, symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength, opt, symbolMeta), symbolMeta;
}(itemModel, symbolSize1, layout, symbolRepeat, 0, symbolOffset, symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength, opt, symbolMeta), symbolMeta;
}
function convertToCoordOnAxis(axis, value) {
return axis.toGlobalCoord(axis.dataToCoord(axis.scale.parse(value)));
Expand Down Expand Up @@ -32125,10 +32125,7 @@
var elStyle = buildElStyle(axisPointerModel), pointerOption = pointerShapeBuilder$1[axisPointerType](axis, polar, coordValue, otherExtent);
pointerOption.style = elStyle, elOption.graphicKey = pointerOption.type, elOption.pointer = pointerOption;
}
var labelMargin = axisPointerModel.get([
'label',
'margin'
]), labelPos = function(value, axisModel, axisPointerModel, polar, labelMargin) {
var labelPos = function(value, axisModel, axisPointerModel, polar, labelMargin) {
var position, align, verticalAlign, axis = axisModel.axis, coord = axis.dataToCoord(value), axisAngle = polar.getAngleAxis().getExtent()[0];
axisAngle = axisAngle / 180 * Math.PI;
var radiusExtent = polar.getRadiusAxis().getExtent();
Expand Down Expand Up @@ -32157,7 +32154,10 @@
align: align,
verticalAlign: verticalAlign
};
}(value, axisModel, axisPointerModel, polar, labelMargin);
}(value, axisModel, 0, polar, axisPointerModel.get([
'label',
'margin'
]));
buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos);
}, PolarAxisPointer;
}(BaseAxisPointer), pointerShapeBuilder$1 = {
Expand Down
6 changes: 3 additions & 3 deletions crates/swc_ecma_minifier/tests/benches-full/victory.js
Expand Up @@ -22575,7 +22575,7 @@
duration: exit
} : {
delay: exit
}), child, data, exitingNodes, function() {
}), 0, data, exitingNodes, function() {
setState({
nodesWillExit: !1
});
Expand Down Expand Up @@ -22615,7 +22615,7 @@
animate: animate,
data: data
};
}(animate1, child, data, enteringNodes, function() {
}(animate1, 0, data, enteringNodes, function() {
setState({
nodesShouldEnter: !0
});
Expand Down Expand Up @@ -22664,7 +22664,7 @@
}),
clipWidth: 0
};
}(animate2, child, data, function() {
}(animate2, 0, data, function() {
setState({
nodesDoneLoad: !0
});
Expand Down
Expand Up @@ -1871,7 +1871,7 @@
};
img.complete ? handleLoad() : img.onload = handleLoad;
}
}(img, srcString, layout, placeholder, onLoadingComplete);
}(img, srcString, 0, placeholder, onLoadingComplete);
},
style: _objectSpread({}, imgStyle, blurStyle)
})), _react.default.createElement("noscript", null, _react.default.createElement("img", Object.assign({}, rest, generateImgAttrs({
Expand Down
Expand Up @@ -6854,7 +6854,7 @@
if ("Exif" !== function(buffer, start, length) {
for(var outstr = "", n = start; n < start + 4; n++)outstr += String.fromCharCode(buffer.getUint8(n));
return outstr;
}(file, start, 4)) return !1;
}(file, start, 0)) return !1;
var bigEnd, tiffOffset = start + 6;
if (0x4949 === file.getUint16(tiffOffset)) bigEnd = !1;
else {
Expand All @@ -6869,10 +6869,10 @@
tag && (tags[tag] = function(file, entryOffset, tiffStart, dirStart, bigEnd) {
var type = file.getUint16(entryOffset + 2, !bigEnd), numValues = file.getUint32(entryOffset + 4, !bigEnd);
return 3 === type && 1 === numValues ? file.getUint16(entryOffset + 8, !bigEnd) : null;
}(file, entryOffset, tiffStart, dirStart, bigEnd));
}(file, entryOffset, 0, 0, bigEnd));
}
return tags;
}(file, tiffOffset, tiffOffset + firstIFDOffset, exifTags, bigEnd);
}(file, 0, tiffOffset + firstIFDOffset, exifTags, bigEnd);
}(dataView, offset + 4, exifTags);
offset += 2 + dataView.getUint16(offset + 2);
}
Expand Down
Expand Up @@ -262,7 +262,7 @@
};
img.complete ? handleLoad() : img.onload = handleLoad;
}
}(img, srcString, layout, placeholder, onLoadingComplete);
}(img, srcString, 0, placeholder, onLoadingComplete);
},
style: _objectSpread({}, imgStyle, blurStyle)
})), _react.default.createElement("noscript", null, _react.default.createElement("img", Object.assign({}, rest, generateImgAttrs({
Expand Down
Expand Up @@ -4607,7 +4607,7 @@
return bestPosition || specifiedPosition;
}(boxPosition, axis);
styleBox.move(bestPosition.toCSSCompatValues(containerBox));
}(window1, styleBox, containerBox, boxPositions), cue.displayState = styleBox.div, boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox));
}(0, styleBox, containerBox, boxPositions), cue.displayState = styleBox.div, boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox));
}();
}, WebVTT1.Parser = function(window1, vttjs, decoder) {
decoder || (decoder = vttjs, vttjs = {}), vttjs || (vttjs = {}), this.window = window1, this.vttjs = vttjs, this.state = "INITIAL", this.buffer = "", this.decoder = decoder || new TextDecoder("utf8"), this.regionList = [];
Expand Down

1 comment on commit d334c6e

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: d334c6e Previous: 1196d60 Ratio
es/full/minify/libraries/antd 1835605752 ns/iter (± 33990897) 1881977142 ns/iter (± 71855182) 0.98
es/full/minify/libraries/d3 382662590 ns/iter (± 9389147) 419415296 ns/iter (± 20257001) 0.91
es/full/minify/libraries/echarts 1499412969 ns/iter (± 37242714) 1588946044 ns/iter (± 349084382) 0.94
es/full/minify/libraries/jquery 108889122 ns/iter (± 7710514) 115908212 ns/iter (± 3820743) 0.94
es/full/minify/libraries/lodash 119918517 ns/iter (± 15788258) 124602934 ns/iter (± 5836729) 0.96
es/full/minify/libraries/moment 61333707 ns/iter (± 3629062) 63079962 ns/iter (± 6260438) 0.97
es/full/minify/libraries/react 20839472 ns/iter (± 657978) 20986871 ns/iter (± 439924) 0.99
es/full/minify/libraries/terser 316413894 ns/iter (± 9960771) 346093801 ns/iter (± 26366051) 0.91
es/full/minify/libraries/three 568830752 ns/iter (± 19534274) 574072728 ns/iter (± 24755760) 0.99
es/full/minify/libraries/typescript 3660215404 ns/iter (± 660756876) 3530298367 ns/iter (± 149807819) 1.04
es/full/minify/libraries/victory 876661032 ns/iter (± 47330961) 862779318 ns/iter (± 32537197) 1.02
es/full/minify/libraries/vue 170811011 ns/iter (± 14684491) 173712947 ns/iter (± 10036254) 0.98
es/full/codegen/es3 34448 ns/iter (± 1354) 33760 ns/iter (± 1317) 1.02
es/full/codegen/es5 33590 ns/iter (± 1258) 33860 ns/iter (± 2275) 0.99
es/full/codegen/es2015 33955 ns/iter (± 2527) 33715 ns/iter (± 1893) 1.01
es/full/codegen/es2016 34019 ns/iter (± 4904) 33965 ns/iter (± 1147) 1.00
es/full/codegen/es2017 33655 ns/iter (± 1111) 33977 ns/iter (± 1806) 0.99
es/full/codegen/es2018 33939 ns/iter (± 2611) 34019 ns/iter (± 1226) 1.00
es/full/codegen/es2019 34113 ns/iter (± 4393) 33878 ns/iter (± 2704) 1.01
es/full/codegen/es2020 34889 ns/iter (± 3230) 33842 ns/iter (± 3373) 1.03
es/full/all/es3 214127632 ns/iter (± 35940118) 234846526 ns/iter (± 26045298) 0.91
es/full/all/es5 202510552 ns/iter (± 16560685) 224490539 ns/iter (± 26923210) 0.90
es/full/all/es2015 162175663 ns/iter (± 12605086) 177936265 ns/iter (± 21215735) 0.91
es/full/all/es2016 163086668 ns/iter (± 15614714) 184969745 ns/iter (± 21741635) 0.88
es/full/all/es2017 165838850 ns/iter (± 26415606) 184631574 ns/iter (± 18678382) 0.90
es/full/all/es2018 158682567 ns/iter (± 15080456) 185366286 ns/iter (± 22034200) 0.86
es/full/all/es2019 161713281 ns/iter (± 13066180) 176036956 ns/iter (± 13497445) 0.92
es/full/all/es2020 156950329 ns/iter (± 36047548) 165864455 ns/iter (± 18491862) 0.95
es/full/parser 747873 ns/iter (± 48044) 783641 ns/iter (± 102978) 0.95
es/full/base/fixer 26636 ns/iter (± 7278) 27816 ns/iter (± 2498) 0.96
es/full/base/resolver_and_hygiene 98503 ns/iter (± 17256) 98238 ns/iter (± 9796) 1.00
serialization of ast node 210 ns/iter (± 5) 213 ns/iter (± 14) 0.99
serialization of serde 210 ns/iter (± 116) 213 ns/iter (± 12) 0.99

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.