diff options
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 71 |
1 files changed, 44 insertions, 27 deletions
diff --git a/lib/compress.js b/lib/compress.js index cfd3e2b2..c30e4b83 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4322,7 +4322,7 @@ merge(Compressor.prototype, { AST_Scope.DEFMETHOD("merge_variables", function(compressor) { if (!compressor.option("merge_vars")) return; - var self = this, segment = null; + var self = this, segment = {}; var first = [], last = [], index = 0; var declarations = new Dictionary(); var references = Object.create(null); @@ -4331,9 +4331,9 @@ merge(Compressor.prototype, { if (node instanceof AST_Assign) { var sym = node.left; if (!(sym instanceof AST_SymbolRef)) return; - if (node.operator != "=") mark(sym); + if (node.operator != "=") mark(sym, true, false); node.right.walk(tw); - mark(sym, true); + mark(sym, false, true); return true; } if (node instanceof AST_Binary) { @@ -4357,6 +4357,7 @@ merge(Compressor.prototype, { if (node instanceof AST_For) { if (node.init) node.init.walk(tw); push(); + segment.block = node; if (node.condition) node.condition.walk(tw); node.body.walk(tw); if (node.step) node.step.walk(tw); @@ -4366,6 +4367,7 @@ merge(Compressor.prototype, { if (node instanceof AST_ForIn) { node.object.walk(tw); push(); + segment.block = node; node.init.walk(tw); node.body.walk(tw); pop(); @@ -4385,12 +4387,14 @@ merge(Compressor.prototype, { } if (node instanceof AST_IterationStatement) { push(); + segment.block = node; descend(); pop(); return true; } if (node instanceof AST_LabeledStatement) { push(); + segment.block = node; node.body.walk(tw); pop(); return true; @@ -4401,6 +4405,7 @@ merge(Compressor.prototype, { if (node.name) references[node.name.definition().id] = false; } push(); + segment.block = node; descend(); pop(); return true; @@ -4422,11 +4427,11 @@ merge(Compressor.prototype, { return true; } if (node instanceof AST_SymbolFunarg) { - if (!node.__unused) mark(node, true); + if (!node.__unused) mark(node, false, true); return true; } if (node instanceof AST_SymbolRef) { - mark(node); + mark(node, true, false); return true; } if (node instanceof AST_Try) { @@ -4446,13 +4451,13 @@ merge(Compressor.prototype, { if (!unary_arithmetic[node.operator]) return; var sym = node.expression; if (!(sym instanceof AST_SymbolRef)) return; - mark(sym); + mark(sym, true, true); return true; } if (node instanceof AST_VarDef) { if (node.value) { node.value.walk(tw); - mark(node.name, true); + mark(node.name, false, true); } else { var id = node.name.definition().id; if (!(id in references)) { @@ -4479,7 +4484,7 @@ merge(Compressor.prototype, { if (tail.index > head.index) continue; var id = tail.definition.id; if (!references[id]) continue; - if (references[def.id].segment !== references[id].segment) { + if (!mergeable()) { skipped.unshift(tail); continue; } @@ -4510,40 +4515,52 @@ merge(Compressor.prototype, { segment = Object.getPrototypeOf(segment); } - function read(def) { - prev[def.id] = last.length; - last.push({ - index: index++, - definition: def, - }); - } - - function mark(sym, write_only) { + function mark(sym, read, write) { var def = sym.definition(); if (def.id in references) { var refs = references[def.id]; if (!refs) return; - if (refs.segment !== segment) return references[def.id] = false; + if (write ? refs.start !== segment : refs.start.block !== segment.block) { + return references[def.id] = false; + } refs.push(sym); - if (def.id in prev) last[prev[def.id]] = null; - read(def); + 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)) { - references[def.id] = false; + return 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({ + if (!read) { + refs.start = segment; + return first.push({ index: index++, definition: def, }); - } else { - refs.segment = self; - read(def); } + refs.start = self; } + prev[def.id] = last.length; + last.push({ + index: index++, + definition: def, + }); + } + + function must_visit(base, segment) { + return base === segment || base.isPrototypeOf(segment); + } + + function mergeable() { + var head = references[def.id]; + var tail = references[id]; + if (head.start.block !== tail.start.block) return false; + return must_visit(head.start, head.end) || must_visit(head.start, tail.start); } }); |