Skip to content

Commit

Permalink
enhance dead_code & side_effects
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Jun 15, 2024
1 parent 0934c0e commit 027e30b
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 20 deletions.
2 changes: 0 additions & 2 deletions lib/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,6 @@ DEF_BITPROPS(AST_Node, [
"private",
// AST_Call
"pure",
// AST_Assign
"redundant",
// AST_Node
"single_use",
// AST_ClassProperty
Expand Down
59 changes: 43 additions & 16 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -638,15 +638,26 @@ Compressor.prototype.compress = function(node) {
}

function push(tw, sequential) {
tw.defined_ids = Object.create(tw.defined_ids);
var safe_ids = Object.create(tw.safe_ids);
if (!sequential) safe_ids.seq = {};
tw.safe_ids = safe_ids;
}

function pop(tw) {
tw.defined_ids = Object.getPrototypeOf(tw.defined_ids);
tw.safe_ids = Object.getPrototypeOf(tw.safe_ids);
}

function access(tw, def) {
tw.defined_ids[def.id] = [ true ];
}

function assign(tw, def) {
var defined = tw.defined_ids[def.id];
if (defined) defined[0] = false;
}

function mark(tw, def) {
tw.safe_ids[def.id] = {};
}
Expand Down Expand Up @@ -939,9 +950,13 @@ Compressor.prototype.compress = function(node) {
return fixed_node;
}, visit);
walk_lambda(fn, tw);
var defined_ids = tw.defined_ids;
var safe_ids = tw.safe_ids;
pop_scope(tw, fn);
if (!aborts) tw.safe_ids = safe_ids;
if (!aborts) {
tw.defined_ids = defined_ids;
tw.safe_ids = safe_ids;
}
return true;

function visit(node, fixed) {
Expand All @@ -966,10 +981,10 @@ Compressor.prototype.compress = function(node) {
var scan = ld || left instanceof AST_Destructured;
switch (node.operator) {
case "=":
if (ld) assign(tw, ld);
if (left.equals(right) && !left.has_side_effects(compressor)) {
right.walk(tw);
walk_prop(left);
node.redundant = true;
return true;
}
if (ld && right instanceof AST_LambdaExpression) {
Expand All @@ -990,6 +1005,7 @@ Compressor.prototype.compress = function(node) {
case "||=":
case "??=":
var lazy = true;
if (ld) assign(tw, ld);
default:
if (!scan) {
mark_assignment_to_arguments(left);
Expand Down Expand Up @@ -1238,6 +1254,12 @@ Compressor.prototype.compress = function(node) {
tw.in_loop = save_loop;
return true;
});
def(AST_Dot, function(tw, descend) {
descend();
var expr = this.expression;
if (expr instanceof AST_SymbolRef) access(tw, expr.definition());
return true;
});
def(AST_For, function(tw, descend, compressor) {
var node = this;
reset_block_variables(tw, compressor, node);
Expand Down Expand Up @@ -1336,10 +1358,13 @@ Compressor.prototype.compress = function(node) {
return true;
});
def(AST_Sub, function(tw) {
if (!this.optional) return;
this.expression.walk(tw);
var node = this;
if (!node.optional) return;
var expr = node.expression;
expr.walk(tw);
if (expr instanceof AST_SymbolRef) access(tw, expr.definition());
push(tw, true);
this.property.walk(tw);
node.property.walk(tw);
pop(tw);
return true;
});
Expand Down Expand Up @@ -1390,6 +1415,7 @@ Compressor.prototype.compress = function(node) {
var d = ref.definition();
var fixed = d.fixed || d.last_ref && d.last_ref.fixed;
push_ref(d, ref);
if ((tw.defined_ids[d.id] || [])[0]) ref.defined = true;
if (d.references.length == 1 && !d.fixed && d.orig[0] instanceof AST_SymbolDefun) {
tw.loop_ids[d.id] = tw.in_loop;
}
Expand Down Expand Up @@ -1618,6 +1644,8 @@ Compressor.prototype.compress = function(node) {
reset_flags(node);
return node.reduce_vars(tw, descend, compressor);
} : reset_flags);
// Side-effect tracking on sequential property access
tw.defined_ids = Object.create(null);
// Flow control for visiting lambda definitions
tw.fn_scanning = null;
tw.fn_visited = [];
Expand Down Expand Up @@ -4712,6 +4740,7 @@ Compressor.prototype.compress = function(node) {
return this.tail_node()._dot_throw(compressor);
});
def(AST_SymbolRef, function(compressor, force) {
if (this.defined) return false;
if (this.is_undefined) return true;
if (!is_strict(compressor, force)) return false;
if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
Expand Down Expand Up @@ -12945,20 +12974,18 @@ Compressor.prototype.compress = function(node) {
if (compressor.option("dead_code")) {
if (self.left instanceof AST_PropAccess) {
if (self.operator == "=") {
if (self.redundant) {
var exprs = [ self.left.expression ];
if (self.left instanceof AST_Sub) exprs.push(self.left.property);
exprs.push(self.right);
return make_sequence(self, exprs).optimize(compressor);
}
if (self.left.equals(self.right) && !self.left.has_side_effects(compressor)) {
return self.right;
}
var exp = self.left.expression;
if (self.left.equals(self.right)) {
var defined = exp.defined;
exp.defined = false;
var drop_lhs = !self.left.has_side_effects(compressor);
exp.defined = defined;
if (drop_lhs) return self.right;
}
if (exp instanceof AST_Lambda
|| !compressor.has_directive("use strict")
&& exp instanceof AST_Constant
&& !exp.may_throw_on_access(compressor)) {
&& exp instanceof AST_Constant
&& !exp.may_throw_on_access(compressor)) {
return self.left instanceof AST_Dot ? self.right : make_sequence(self, [
self.left.property,
self.right
Expand Down
2 changes: 1 addition & 1 deletion test/compress/arrows.js
Original file line number Diff line number Diff line change
Expand Up @@ -1312,7 +1312,7 @@ issue_5653: {
}
expect: {
console.log((a => {
return console, +{};
return +{};
})());
}
expect_stdout: "NaN"
Expand Down
2 changes: 1 addition & 1 deletion test/compress/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -8200,7 +8200,7 @@ issue_5316_1: {
expect: {
do {
console.log("PASS");
} while (b = a = void 0, b = (42, console[a = a] = a++), void 0);
} while (b = (42, console[a = b = a = void 0] = a++), void 0);
var a, b;
}
expect_stdout: "PASS"
Expand Down
62 changes: 62 additions & 0 deletions test/compress/side_effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -724,3 +724,65 @@ retain_instanceof: {
}
expect_stdout: "PASS"
}

drop_access: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var o = {};
o.p;
var f = function() {
o.q;
};
f();
console.log("PASS");
}
expect: {
var o = {};
o.p;
var f = function() {};
f();
console.log("PASS");
}
expect_stdout: "PASS"
}

keep_access: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var o = {};
o.p;
o = null;
var f = function() {
o.q;
};
try {
f();
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect: {
var o = {};
o.p;
o = null;
var f = function() {
o.q;
};
try {
f();
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}

0 comments on commit 027e30b

Please sign in to comment.