enhance merge_vars (#4125)

This commit is contained in:
Alex Lam S.L
2020-09-19 04:16:23 +01:00
committed by GitHub
parent 38a46c86d7
commit 3ac533e644
2 changed files with 2136 additions and 37 deletions

View File

@@ -4322,7 +4322,7 @@ merge(Compressor.prototype, {
AST_Scope.DEFMETHOD("merge_variables", function(compressor) { AST_Scope.DEFMETHOD("merge_variables", function(compressor) {
if (!compressor.option("merge_vars")) return; if (!compressor.option("merge_vars")) return;
var self = this, segment = null; var self = this, segment = {};
var first = [], last = [], index = 0; var first = [], last = [], index = 0;
var declarations = new Dictionary(); var declarations = new Dictionary();
var references = Object.create(null); var references = Object.create(null);
@@ -4331,9 +4331,9 @@ merge(Compressor.prototype, {
if (node instanceof AST_Assign) { if (node instanceof AST_Assign) {
var sym = node.left; var sym = node.left;
if (!(sym instanceof AST_SymbolRef)) return; if (!(sym instanceof AST_SymbolRef)) return;
if (node.operator != "=") mark(sym); if (node.operator != "=") mark(sym, true, false);
node.right.walk(tw); node.right.walk(tw);
mark(sym, true); mark(sym, false, true);
return true; return true;
} }
if (node instanceof AST_Binary) { if (node instanceof AST_Binary) {
@@ -4357,6 +4357,7 @@ merge(Compressor.prototype, {
if (node instanceof AST_For) { if (node instanceof AST_For) {
if (node.init) node.init.walk(tw); if (node.init) node.init.walk(tw);
push(); push();
segment.block = node;
if (node.condition) node.condition.walk(tw); if (node.condition) node.condition.walk(tw);
node.body.walk(tw); node.body.walk(tw);
if (node.step) node.step.walk(tw); if (node.step) node.step.walk(tw);
@@ -4366,6 +4367,7 @@ merge(Compressor.prototype, {
if (node instanceof AST_ForIn) { if (node instanceof AST_ForIn) {
node.object.walk(tw); node.object.walk(tw);
push(); push();
segment.block = node;
node.init.walk(tw); node.init.walk(tw);
node.body.walk(tw); node.body.walk(tw);
pop(); pop();
@@ -4385,12 +4387,14 @@ merge(Compressor.prototype, {
} }
if (node instanceof AST_IterationStatement) { if (node instanceof AST_IterationStatement) {
push(); push();
segment.block = node;
descend(); descend();
pop(); pop();
return true; return true;
} }
if (node instanceof AST_LabeledStatement) { if (node instanceof AST_LabeledStatement) {
push(); push();
segment.block = node;
node.body.walk(tw); node.body.walk(tw);
pop(); pop();
return true; return true;
@@ -4401,6 +4405,7 @@ merge(Compressor.prototype, {
if (node.name) references[node.name.definition().id] = false; if (node.name) references[node.name.definition().id] = false;
} }
push(); push();
segment.block = node;
descend(); descend();
pop(); pop();
return true; return true;
@@ -4422,11 +4427,11 @@ merge(Compressor.prototype, {
return true; return true;
} }
if (node instanceof AST_SymbolFunarg) { if (node instanceof AST_SymbolFunarg) {
if (!node.__unused) mark(node, true); if (!node.__unused) mark(node, false, true);
return true; return true;
} }
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
mark(node); mark(node, true, false);
return true; return true;
} }
if (node instanceof AST_Try) { if (node instanceof AST_Try) {
@@ -4446,13 +4451,13 @@ merge(Compressor.prototype, {
if (!unary_arithmetic[node.operator]) return; if (!unary_arithmetic[node.operator]) return;
var sym = node.expression; var sym = node.expression;
if (!(sym instanceof AST_SymbolRef)) return; if (!(sym instanceof AST_SymbolRef)) return;
mark(sym); mark(sym, true, true);
return true; return true;
} }
if (node instanceof AST_VarDef) { if (node instanceof AST_VarDef) {
if (node.value) { if (node.value) {
node.value.walk(tw); node.value.walk(tw);
mark(node.name, true); mark(node.name, false, true);
} else { } else {
var id = node.name.definition().id; var id = node.name.definition().id;
if (!(id in references)) { if (!(id in references)) {
@@ -4479,7 +4484,7 @@ merge(Compressor.prototype, {
if (tail.index > head.index) continue; if (tail.index > head.index) continue;
var id = tail.definition.id; var id = tail.definition.id;
if (!references[id]) continue; if (!references[id]) continue;
if (references[def.id].segment !== references[id].segment) { if (!mergeable()) {
skipped.unshift(tail); skipped.unshift(tail);
continue; continue;
} }
@@ -4510,7 +4515,36 @@ merge(Compressor.prototype, {
segment = Object.getPrototypeOf(segment); segment = Object.getPrototypeOf(segment);
} }
function read(def) { function mark(sym, read, write) {
var def = sym.definition();
if (def.id in references) {
var refs = references[def.id];
if (!refs) return;
if (write ? refs.start !== segment : refs.start.block !== segment.block) {
return references[def.id] = false;
}
refs.push(sym);
refs.end = segment;
if (def.id in prev) {
last[prev[def.id]] = null;
} else if (!read) {
return;
}
} else if (self.variables.get(def.name) !== def || compressor.exposed(def)) {
return references[def.id] = false;
} else {
var refs = declarations.get(def.id) || [];
refs.push(sym);
references[def.id] = refs;
if (!read) {
refs.start = segment;
return first.push({
index: index++,
definition: def,
});
}
refs.start = self;
}
prev[def.id] = last.length; prev[def.id] = last.length;
last.push({ last.push({
index: index++, index: index++,
@@ -4518,32 +4552,15 @@ merge(Compressor.prototype, {
}); });
} }
function mark(sym, write_only) { function must_visit(base, segment) {
var def = sym.definition(); return base === segment || base.isPrototypeOf(segment);
if (def.id in references) { }
var refs = references[def.id];
if (!refs) return; function mergeable() {
if (refs.segment !== segment) return references[def.id] = false; var head = references[def.id];
refs.push(sym); var tail = references[id];
if (def.id in prev) last[prev[def.id]] = null; if (head.start.block !== tail.start.block) return false;
read(def); return must_visit(head.start, head.end) || must_visit(head.start, tail.start);
} else if (self.variables.get(def.name) !== def || compressor.exposed(def)) {
references[def.id] = false;
} else {
var refs = declarations.get(def.id) || [];
refs.push(sym);
references[def.id] = refs;
if (write_only) {
refs.segment = segment;
first.push({
index: index++,
definition: def,
});
} else {
refs.segment = self;
read(def);
}
}
} }
}); });

File diff suppressed because it is too large Load Diff