[Pkg-javascript-commits] [uglifyjs] 342/491: improve `reset_opt_flags()` (#2610)

Jonas Smedegaard dr at jones.dk
Wed Feb 14 19:51:51 UTC 2018


This is an automated email from the git hooks/post-receive script.

js pushed a commit to annotated tag debian/3.3.10-1
in repository uglifyjs.

commit 7918a50d52809a854d6808c7a97f87f8e256506e
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date:   Sun Dec 17 23:01:08 2017 +0800

    improve `reset_opt_flags()` (#2610)
---
 lib/compress.js | 604 +++++++++++++++++++++++++++++---------------------------
 1 file changed, 311 insertions(+), 293 deletions(-)

diff --git a/lib/compress.js b/lib/compress.js
index ebcae48..bccd763 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -293,14 +293,12 @@ merge(Compressor.prototype, {
                 if (index >= 0) {
                     node.body[index] = node.body[index].transform(tt);
                 }
-            }
-            if (node instanceof AST_If) {
+            } else if (node instanceof AST_If) {
                 node.body = node.body.transform(tt);
                 if (node.alternative) {
                     node.alternative = node.alternative.transform(tt);
                 }
-            }
-            if (node instanceof AST_With) {
+            } else if (node instanceof AST_With) {
                 node.body = node.body.transform(tt);
             }
             return node;
@@ -308,262 +306,44 @@ merge(Compressor.prototype, {
         self.transform(tt);
     });
 
-    AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
-        var reduce_vars = compressor.option("reduce_vars");
-        var unused = compressor.option("unused");
-        // Stack of look-up tables to keep track of whether a `SymbolDef` has been
-        // properly assigned before use:
-        // - `push()` & `pop()` when visiting conditional branches
-        // - backup & restore via `save_ids` when visiting out-of-order sections
-        var safe_ids = Object.create(null);
-        var suppressor = new TreeWalker(function(node) {
-            if (!(node instanceof AST_Symbol)) return;
-            var d = node.definition();
-            if (!d) return;
-            if (node instanceof AST_SymbolRef) d.references.push(node);
-            d.fixed = false;
-        });
-        var in_loop = null;
-        var loop_ids = Object.create(null);
-        var tw = new TreeWalker(function(node, descend) {
-            node._squeezed = false;
-            node._optimized = false;
-            if (reduce_vars) {
-                if (node instanceof AST_Toplevel) node.globals.each(reset_def);
-                if (node instanceof AST_Scope) node.variables.each(reset_def);
-                if (node instanceof AST_SymbolRef) {
-                    var d = node.definition();
-                    d.references.push(node);
-                    if (d.references.length == 1
-                        && !d.fixed
-                        && d.orig[0] instanceof AST_SymbolDefun) {
-                        loop_ids[d.id] = in_loop;
-                    }
-                    var value;
-                    if (d.fixed === undefined || !safe_to_read(d) || d.single_use == "m") {
-                        d.fixed = false;
-                    } else if (d.fixed) {
-                        value = node.fixed_value();
-                        if (value && ref_once(d)) {
-                            d.single_use = value instanceof AST_Lambda
-                                || d.scope === node.scope && value.is_constant_expression();
-                        } else {
-                            d.single_use = false;
-                        }
-                        if (is_modified(node, value, 0, is_immutable(value))) {
-                            if (d.single_use) {
-                                d.single_use = "m";
-                            } else {
-                                d.fixed = false;
-                            }
-                        }
-                    }
-                    mark_escaped(d, node.scope, node, value, 0);
-                }
-                if (node instanceof AST_SymbolCatch) {
-                    node.definition().fixed = false;
-                }
-                if (node instanceof AST_VarDef) {
-                    var d = node.name.definition();
-                    if (d.fixed === undefined || safe_to_assign(d, node.value)) {
-                        if (node.value) {
-                            d.fixed = function() {
-                                return node.value;
-                            };
-                            loop_ids[d.id] = in_loop;
-                            mark(d, false);
-                            descend();
-                        } else {
-                            d.fixed = null;
-                        }
-                        mark(d, true);
-                        return true;
-                    } else if (node.value) {
-                        d.fixed = false;
-                    }
-                }
-                if (node instanceof AST_Assign
-                    && node.operator == "="
-                    && node.left instanceof AST_SymbolRef) {
-                    var d = node.left.definition();
-                    if (safe_to_assign(d, node.right)
-                        || d.fixed === undefined && all(d.orig, function(sym) {
-                            return sym instanceof AST_SymbolVar;
-                        })) {
-                        d.references.push(node.left);
-                        d.fixed = function() {
-                            return node.right;
-                        };
-                        mark(d, false);
-                        node.right.walk(tw);
-                        mark(d, true);
-                        return true;
-                    }
-                }
-                if (node instanceof AST_Defun) {
-                    node.inlined = false;
-                    var d = node.name.definition();
-                    if (compressor.exposed(d) || safe_to_read(d)) {
-                        d.fixed = false;
-                    } else {
-                        d.fixed = node;
-                        d.single_use = ref_once(d);
-                        loop_ids[d.id] = in_loop;
-                        mark(d, true);
-                    }
-                    var save_ids = safe_ids;
-                    safe_ids = Object.create(null);
-                    descend();
-                    safe_ids = save_ids;
-                    return true;
-                }
-                if (node instanceof AST_Function) {
-                    node.inlined = false;
-                    push();
-                    var iife;
-                    if (!node.name
-                        && (iife = tw.parent()) instanceof AST_Call
-                        && iife.expression === node) {
-                        // Virtually turn IIFE parameters into variable definitions:
-                        //   (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
-                        // So existing transformation rules can work on them.
-                        node.argnames.forEach(function(arg, i) {
-                            var d = arg.definition();
-                            if (!node.uses_arguments && d.fixed === undefined) {
-                                d.fixed = function() {
-                                    return iife.args[i] || make_node(AST_Undefined, iife);
-                                };
-                                loop_ids[d.id] = in_loop;
-                                mark(d, true);
-                            } else {
-                                d.fixed = false;
-                            }
-                        });
-                    }
-                    descend();
-                    pop();
-                    return true;
-                }
-                if (node instanceof AST_Accessor) {
-                    push();
-                    descend();
-                    pop();
-                    return true;
-                }
-                if (node instanceof AST_Binary && lazy_op(node.operator)) {
-                    node.left.walk(tw);
-                    push();
-                    node.right.walk(tw);
-                    pop();
-                    return true;
-                }
-                if (node instanceof AST_Conditional) {
-                    node.condition.walk(tw);
-                    push();
-                    node.consequent.walk(tw);
-                    pop();
-                    push();
-                    node.alternative.walk(tw);
-                    pop();
-                    return true;
-                }
-                if (node instanceof AST_If) {
-                    node.condition.walk(tw);
-                    push();
-                    node.body.walk(tw);
-                    pop();
-                    if (node.alternative) {
-                        push();
-                        node.alternative.walk(tw);
-                        pop();
-                    }
-                    return true;
-                }
-                if (node instanceof AST_Do) {
-                    var saved_loop = in_loop;
-                    in_loop = node;
-                    push();
-                    node.body.walk(tw);
-                    node.condition.walk(tw);
-                    pop();
-                    in_loop = saved_loop;
-                    return true;
-                }
-                if (node instanceof AST_While) {
-                    var saved_loop = in_loop;
-                    in_loop = node;
-                    push();
-                    node.condition.walk(tw);
-                    node.body.walk(tw);
-                    pop();
-                    in_loop = saved_loop;
-                    return true;
-                }
-                if (node instanceof AST_LabeledStatement) {
-                    push();
-                    node.body.walk(tw);
-                    pop();
-                    return true;
-                }
-                if (node instanceof AST_For) {
-                    if (node.init) node.init.walk(tw);
-                    var saved_loop = in_loop;
-                    in_loop = node;
-                    if (node.condition) {
-                        push();
-                        node.condition.walk(tw);
-                        pop();
-                    }
-                    push();
-                    node.body.walk(tw);
-                    pop();
-                    if (node.step) {
-                        push();
-                        node.step.walk(tw);
-                        pop();
-                    }
-                    in_loop = saved_loop;
-                    return true;
-                }
-                if (node instanceof AST_ForIn) {
-                    node.init.walk(suppressor);
-                    node.object.walk(tw);
-                    var saved_loop = in_loop;
-                    in_loop = node;
-                    push();
-                    node.body.walk(tw);
-                    pop();
-                    in_loop = saved_loop;
-                    return true;
-                }
-                if (node instanceof AST_Try) {
-                    push();
-                    walk_body(node, tw);
-                    pop();
-                    if (node.bcatch) {
-                        push();
-                        node.bcatch.walk(tw);
-                        pop();
-                    }
-                    if (node.bfinally) node.bfinally.walk(tw);
-                    return true;
-                }
-                if (node instanceof AST_SwitchBranch) {
-                    push();
-                    descend();
-                    pop();
-                    return true;
-                }
+    (function(def){
+        def(AST_Node, noop);
+
+        function reset_def(compressor, def) {
+            def.direct_access = false;
+            def.escaped = false;
+            if (def.scope.uses_eval || def.scope.uses_with) {
+                def.fixed = false;
+            } else if (!compressor.exposed(def)) {
+                def.fixed = undefined;
+            } else {
+                def.fixed = false;
             }
-        });
-        this.walk(tw);
+            def.references = [];
+            def.should_replace = undefined;
+            def.single_use = undefined;
+        }
+
+        function reset_variables(compressor, node) {
+            node.variables.each(function(def) {
+                reset_def(compressor, def);
+            });
+        }
 
-        function mark(def, safe) {
-            safe_ids[def.id] = safe;
+        function push(tw) {
+            tw.safe_ids = Object.create(tw.safe_ids);
         }
 
-        function safe_to_read(def) {
-            if (safe_ids[def.id]) {
+        function pop(tw) {
+            tw.safe_ids = Object.getPrototypeOf(tw.safe_ids);
+        }
+
+        function mark(tw, def, safe) {
+            tw.safe_ids[def.id] = safe;
+        }
+
+        function safe_to_read(tw, def) {
+            if (tw.safe_ids[def.id]) {
                 if (def.fixed == null) {
                     var orig = def.orig[0];
                     if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
@@ -574,9 +354,9 @@ merge(Compressor.prototype, {
             return def.fixed instanceof AST_Defun;
         }
 
-        function safe_to_assign(def, value) {
-            if (!HOP(safe_ids, def.id)) return false;
-            if (!safe_to_read(def)) return false;
+        function safe_to_assign(tw, def, value) {
+            if (!HOP(tw.safe_ids, def.id)) return false;
+            if (!safe_to_read(tw, def)) return false;
             if (def.fixed === false) return false;
             if (def.fixed != null && (!value || def.references.length > 0)) return false;
             return all(def.orig, function(sym) {
@@ -585,35 +365,12 @@ merge(Compressor.prototype, {
             });
         }
 
-        function push() {
-            safe_ids = Object.create(safe_ids);
-        }
-
-        function pop() {
-            safe_ids = Object.getPrototypeOf(safe_ids);
-        }
-
-        function reset_def(def) {
-            def.direct_access = false;
-            def.escaped = false;
-            if (def.scope.uses_eval || def.scope.uses_with) {
-                def.fixed = false;
-            } else if (!compressor.exposed(def)) {
-                def.fixed = undefined;
-            } else {
-                def.fixed = false;
-            }
-            def.references = [];
-            def.should_replace = undefined;
-            def.single_use = undefined;
-        }
-
-        function ref_once(def) {
-            return unused
+        function ref_once(tw, compressor, def) {
+            return compressor.option("unused")
                 && !def.scope.uses_eval
                 && !def.scope.uses_with
                 && def.references.length == 1
-                && loop_ids[def.id] === in_loop;
+                && tw.loop_ids[def.id] === tw.in_loop;
         }
 
         function is_immutable(value) {
@@ -642,7 +399,7 @@ merge(Compressor.prototype, {
             return value instanceof AST_SymbolRef && value.fixed_value() || value;
         }
 
-        function is_modified(node, value, level, immutable) {
+        function is_modified(tw, node, value, level, immutable) {
             var parent = tw.parent(level);
             if (is_lhs(node, parent)
                 || !immutable
@@ -652,16 +409,16 @@ merge(Compressor.prototype, {
                         || !(parent instanceof AST_New) && value.contains_this())) {
                 return true;
             } else if (parent instanceof AST_Array) {
-                return is_modified(parent, parent, level + 1);
+                return is_modified(tw, parent, parent, level + 1);
             } else if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
                 var obj = tw.parent(level + 1);
-                return is_modified(obj, obj, level + 2);
+                return is_modified(tw, obj, obj, level + 2);
             } else if (parent instanceof AST_PropAccess && parent.expression === node) {
-                return !immutable && is_modified(parent, read_property(value, parent.property), level + 1);
+                return !immutable && is_modified(tw, parent, read_property(value, parent.property), level + 1);
             }
         }
 
-        function mark_escaped(d, scope, node, value, level) {
+        function mark_escaped(tw, d, scope, node, value, level) {
             var parent = tw.parent(level);
             if (value) {
                 if (value.is_constant()) return;
@@ -677,17 +434,278 @@ merge(Compressor.prototype, {
                 || parent instanceof AST_Binary && lazy_op(parent.operator)
                 || parent instanceof AST_Conditional && node !== parent.condition
                 || parent instanceof AST_Sequence && node === parent.tail_node()) {
-                mark_escaped(d, scope, parent, parent, level + 1);
+                mark_escaped(tw, d, scope, parent, parent, level + 1);
             } else if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
                 var obj = tw.parent(level + 1);
-                mark_escaped(d, scope, obj, obj, level + 2);
+                mark_escaped(tw, d, scope, obj, obj, level + 2);
             } else if (parent instanceof AST_PropAccess && node === parent.expression) {
                 value = read_property(value, parent.property);
-                mark_escaped(d, scope, parent, value, level + 1);
+                mark_escaped(tw, d, scope, parent, value, level + 1);
                 if (value) return;
             }
             if (level == 0) d.direct_access = true;
         }
+
+        var suppressor = new TreeWalker(function(node) {
+            if (!(node instanceof AST_Symbol)) return;
+            var d = node.definition();
+            if (!d) return;
+            if (node instanceof AST_SymbolRef) d.references.push(node);
+            d.fixed = false;
+        });
+        def(AST_Accessor, function(tw, descend) {
+            push(tw);
+            descend();
+            pop(tw);
+            return true;
+        });
+        def(AST_Assign, function(tw) {
+            var node = this;
+            if (node.operator != "=" || !(node.left instanceof AST_SymbolRef)) return;
+            var d = node.left.definition();
+            if (safe_to_assign(tw, d, node.right)
+                || d.fixed === undefined && all(d.orig, function(sym) {
+                    return sym instanceof AST_SymbolVar;
+                })) {
+                d.references.push(node.left);
+                d.fixed = function() {
+                    return node.right;
+                };
+                mark(tw, d, false);
+                node.right.walk(tw);
+                mark(tw, d, true);
+                return true;
+            }
+        });
+        def(AST_Binary, function(tw) {
+            if (!lazy_op(this.operator)) return;
+            this.left.walk(tw);
+            push(tw);
+            this.right.walk(tw);
+            pop(tw);
+            return true;
+        });
+        def(AST_Conditional, function(tw) {
+            this.condition.walk(tw);
+            push(tw);
+            this.consequent.walk(tw);
+            pop(tw);
+            push(tw);
+            this.alternative.walk(tw);
+            pop(tw);
+            return true;
+        });
+        def(AST_Defun, function(tw, descend, compressor) {
+            reset_variables(compressor, this);
+            this.inlined = false;
+            var d = this.name.definition();
+            if (compressor.exposed(d) || safe_to_read(tw, d)) {
+                d.fixed = false;
+            } else {
+                d.fixed = this;
+                d.single_use = ref_once(tw, compressor, d);
+                tw.loop_ids[d.id] = tw.in_loop;
+                mark(tw, d, true);
+            }
+            var save_ids = tw.safe_ids;
+            tw.safe_ids = Object.create(null);
+            descend();
+            tw.safe_ids = save_ids;
+            return true;
+        });
+        def(AST_Do, function(tw) {
+            var saved_loop = tw.in_loop;
+            tw.in_loop = this;
+            push(tw);
+            this.body.walk(tw);
+            this.condition.walk(tw);
+            pop(tw);
+            tw.in_loop = saved_loop;
+            return true;
+        });
+        def(AST_For, function(tw) {
+            if (this.init) this.init.walk(tw);
+            var saved_loop = tw.in_loop;
+            tw.in_loop = this;
+            if (this.condition) {
+                push(tw);
+                this.condition.walk(tw);
+                pop(tw);
+            }
+            push(tw);
+            this.body.walk(tw);
+            pop(tw);
+            if (this.step) {
+                push(tw);
+                this.step.walk(tw);
+                pop(tw);
+            }
+            tw.in_loop = saved_loop;
+            return true;
+        });
+        def(AST_ForIn, function(tw) {
+            this.init.walk(suppressor);
+            this.object.walk(tw);
+            var saved_loop = tw.in_loop;
+            tw.in_loop = this;
+            push(tw);
+            this.body.walk(tw);
+            pop(tw);
+            tw.in_loop = saved_loop;
+            return true;
+        });
+        def(AST_Function, function(tw, descend, compressor) {
+            var node = this;
+            reset_variables(compressor, node);
+            node.inlined = false;
+            push(tw);
+            var iife;
+            if (!node.name
+                && (iife = tw.parent()) instanceof AST_Call
+                && iife.expression === node) {
+                // Virtually turn IIFE parameters into variable definitions:
+                //   (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
+                // So existing transformation rules can work on them.
+                node.argnames.forEach(function(arg, i) {
+                    var d = arg.definition();
+                    if (!node.uses_arguments && d.fixed === undefined) {
+                        d.fixed = function() {
+                            return iife.args[i] || make_node(AST_Undefined, iife);
+                        };
+                        tw.loop_ids[d.id] = tw.in_loop;
+                        mark(tw, d, true);
+                    } else {
+                        d.fixed = false;
+                    }
+                });
+            }
+            descend();
+            pop(tw);
+            return true;
+        });
+        def(AST_If, function(tw) {
+            this.condition.walk(tw);
+            push(tw);
+            this.body.walk(tw);
+            pop(tw);
+            if (this.alternative) {
+                push(tw);
+                this.alternative.walk(tw);
+                pop(tw);
+            }
+            return true;
+        });
+        def(AST_LabeledStatement, function(tw) {
+            push(tw);
+            this.body.walk(tw);
+            pop(tw);
+            return true;
+        });
+        def(AST_SwitchBranch, function(tw, descend) {
+            push(tw);
+            descend();
+            pop(tw);
+            return true;
+        });
+        def(AST_SymbolCatch, function() {
+            this.definition().fixed = false;
+        });
+        def(AST_SymbolRef, function(tw, descend, compressor) {
+            var d = this.definition();
+            d.references.push(this);
+            if (d.references.length == 1
+                && !d.fixed
+                && d.orig[0] instanceof AST_SymbolDefun) {
+                tw.loop_ids[d.id] = tw.in_loop;
+            }
+            var value;
+            if (d.fixed === undefined || !safe_to_read(tw, d) || d.single_use == "m") {
+                d.fixed = false;
+            } else if (d.fixed) {
+                value = this.fixed_value();
+                if (value && ref_once(tw, compressor, d)) {
+                    d.single_use = value instanceof AST_Lambda
+                        || d.scope === this.scope && value.is_constant_expression();
+                } else {
+                    d.single_use = false;
+                }
+                if (is_modified(tw, this, value, 0, is_immutable(value))) {
+                    if (d.single_use) {
+                        d.single_use = "m";
+                    } else {
+                        d.fixed = false;
+                    }
+                }
+            }
+            mark_escaped(tw, d, this.scope, this, value, 0);
+        });
+        def(AST_Toplevel, function(tw, descend, compressor) {
+            this.globals.each(function(def) {
+                reset_def(compressor, def);
+            });
+            reset_variables(compressor, this);
+        });
+        def(AST_Try, function(tw) {
+            push(tw);
+            walk_body(this, tw);
+            pop(tw);
+            if (this.bcatch) {
+                push(tw);
+                this.bcatch.walk(tw);
+                pop(tw);
+            }
+            if (this.bfinally) this.bfinally.walk(tw);
+            return true;
+        });
+        def(AST_VarDef, function(tw, descend) {
+            var node = this;
+            var d = node.name.definition();
+            if (d.fixed === undefined || safe_to_assign(tw, d, node.value)) {
+                if (node.value) {
+                    d.fixed = function() {
+                        return node.value;
+                    };
+                    tw.loop_ids[d.id] = tw.in_loop;
+                    mark(tw, d, false);
+                    descend();
+                } else {
+                    d.fixed = null;
+                }
+                mark(tw, d, true);
+                return true;
+            } else if (node.value) {
+                d.fixed = false;
+            }
+        });
+        def(AST_While, function(tw) {
+            var saved_loop = tw.in_loop;
+            tw.in_loop = this;
+            push(tw);
+            this.condition.walk(tw);
+            this.body.walk(tw);
+            pop(tw);
+            tw.in_loop = saved_loop;
+            return true;
+        });
+    })(function(node, func){
+        node.DEFMETHOD("reduce_vars", func);
+    });
+
+    AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
+        var reduce_vars = compressor.option("reduce_vars");
+        var tw = new TreeWalker(function(node, descend) {
+            node._squeezed = false;
+            node._optimized = false;
+            if (reduce_vars) return node.reduce_vars(tw, descend, compressor);
+        });
+        // Stack of look-up tables to keep track of whether a `SymbolDef` has been
+        // properly assigned before use:
+        // - `push()` & `pop()` when visiting conditional branches
+        // - backup & restore via `save_ids` when visiting out-of-order sections
+        tw.safe_ids = Object.create(null);
+        tw.in_loop = null;
+        tw.loop_ids = Object.create(null);
+        this.walk(tw);
     });
 
     AST_Symbol.DEFMETHOD("fixed_value", function() {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git



More information about the Pkg-javascript-commits mailing list