fix corner case in reduce_vars (#3241)

fixes #3240
This commit is contained in:
Alex Lam S.L
2018-08-29 22:14:25 +08:00
committed by GitHub
parent f352bcec3a
commit aa0029204e
2 changed files with 183 additions and 27 deletions

View File

@@ -5751,38 +5751,34 @@ merge(Compressor.prototype, {
}
var parent = compressor.parent();
if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
var d = self.definition();
var def = self.definition();
var fixed = self.fixed_value();
var single_use = d.single_use
&& !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
var single_use = def.single_use && !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
if (single_use && fixed instanceof AST_Lambda) {
if (d.scope !== self.scope
&& (!compressor.option("reduce_funcs")
|| d.escaped == 1
|| fixed.inlined)) {
if (def.scope !== self.scope
&& (!compressor.option("reduce_funcs") || def.escaped == 1 || fixed.inlined)) {
single_use = false;
} else if (recursive_ref(compressor, d)) {
} else if (recursive_ref(compressor, def)) {
single_use = false;
} else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) {
} else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
single_use = fixed.is_constant_expression(self.scope);
if (single_use == "f") {
var scope = self.scope;
do {
if (scope instanceof AST_Defun || scope instanceof AST_Function) {
scope.inlined = true;
}
do if (scope instanceof AST_Defun || scope instanceof AST_Function) {
scope.inlined = true;
} while (scope = scope.parent_scope);
}
}
}
if (single_use && fixed) {
def.single_use = false;
if (fixed instanceof AST_Defun) {
fixed._squeezed = true;
fixed = make_node(AST_Function, fixed, fixed);
fixed.name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
}
var value;
if (d.recursive_refs > 0) {
if (def.recursive_refs > 0) {
value = fixed.clone(true);
var defun_def = value.name.definition();
var lambda_def = value.variables.get(value.name.name);
@@ -5794,9 +5790,13 @@ merge(Compressor.prototype, {
lambda_def = value.def_function(name);
}
value.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
if (!(node instanceof AST_SymbolRef)) return;
var def = node.definition();
if (def === defun_def) {
node.thedef = lambda_def;
lambda_def.references.push(node);
} else {
def.single_use = false;
}
}));
} else {
@@ -5805,13 +5805,12 @@ merge(Compressor.prototype, {
}
return value;
}
if (fixed && d.should_replace === undefined) {
if (fixed && def.should_replace === undefined) {
var init;
if (fixed instanceof AST_This) {
if (!(d.orig[0] instanceof AST_SymbolFunarg)
&& all(d.references, function(ref) {
return d.scope === ref.scope;
})) {
if (!(def.orig[0] instanceof AST_SymbolFunarg) && all(def.references, function(ref) {
return def.scope === ref.scope;
})) {
init = fixed;
}
} else {
@@ -5835,18 +5834,18 @@ merge(Compressor.prototype, {
return result === init || result === fixed ? result.clone(true) : result;
};
}
var name_length = d.name.length;
var name_length = def.name.length;
var overhead = 0;
if (compressor.option("unused") && !compressor.exposed(d)) {
overhead = (name_length + 2 + value_length) / (d.references.length - d.assignments);
if (compressor.option("unused") && !compressor.exposed(def)) {
overhead = (name_length + 2 + value_length) / (def.references.length - def.assignments);
}
d.should_replace = value_length <= name_length + overhead ? fn : false;
def.should_replace = value_length <= name_length + overhead ? fn : false;
} else {
d.should_replace = false;
def.should_replace = false;
}
}
if (d.should_replace) {
return d.should_replace();
if (def.should_replace) {
return def.should_replace();
}
}
return self;

View File

@@ -5354,6 +5354,7 @@ issue_2774: {
issue_2799_1: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -6429,3 +6430,159 @@ issue_3140_5: {
}
expect_stdout: "1"
}
issue_3240_1: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f(1);
function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
}
})();
}
expect: {
(function() {
(function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
})(1);
})();
}
expect_stdout: [
"1",
"0",
]
}
issue_3240_2: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f(1);
function f(a) {
console.log(a);
var g = function() {
f(a - 1);
};
if (a) g();
}
})();
}
expect: {
(function() {
(function f(a) {
console.log(a);
if (a) (function() {
f(a - 1);
})();
})(1);
})();
}
expect_stdout: [
"1",
"0",
]
}
issue_3240_3: {
options = {
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f();
function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
}
})();
}
expect: {
(function() {
(function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
})();
})();
}
expect_stdout: [
"0",
"1",
]
}
issue_3240_4: {
options = {
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
f();
function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
var g = function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
};
g();
}
})();
}
expect: {
(function() {
(function f(b) {
if (!f.a) f.a = 0;
console.log(f.a.toString());
(function() {
(b ? function() {} : function() {
f.a++;
f(1);
})();
})();
})();
})();
}
expect_stdout: [
"0",
"1",
]
}