From 4832bc5d88e37ca35f1dd5f5d8ddd95cd8bbdd7d Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Tue, 26 Dec 2017 21:25:35 +0800 Subject: replace single-use recursive functions (#2659) fixes #2628 --- lib/compress.js | 39 +++++++++++++++++++++++++++++---------- lib/scope.js | 4 +++- 2 files changed, 32 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/compress.js b/lib/compress.js index bb355423..d890caf7 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -319,6 +319,7 @@ merge(Compressor.prototype, { } else { def.fixed = false; } + def.recursive_refs = 0; def.references = []; def.should_replace = undefined; def.single_use = undefined; @@ -369,7 +370,7 @@ merge(Compressor.prototype, { return compressor.option("unused") && !def.scope.uses_eval && !def.scope.uses_with - && def.references.length == 1 + && def.references.length - def.recursive_refs == 1 && tw.loop_ids[def.id] === tw.in_loop; } @@ -621,7 +622,9 @@ merge(Compressor.prototype, { d.fixed = false; } else if (d.fixed) { value = this.fixed_value(); - if (value && ref_once(tw, compressor, d)) { + if (value instanceof AST_Lambda && recursive_ref(tw, d)) { + d.recursive_refs++; + } else if (value && ref_once(tw, compressor, d)) { d.single_use = value instanceof AST_Lambda || d.scope === this.scope && value.is_constant_expression(); } else { @@ -4670,17 +4673,18 @@ merge(Compressor.prototype, { if (fixed instanceof AST_Defun) { d.fixed = fixed = make_node(AST_Function, fixed, fixed); } - if (d.single_use && fixed instanceof AST_Function) { + var single_use = d.single_use; + if (single_use && fixed instanceof AST_Function) { if (d.scope !== self.scope && (!compressor.option("reduce_funcs") || d.escaped == 1 || fixed.inlined)) { - d.single_use = false; + single_use = false; } else if (recursive_ref(compressor, d)) { - d.single_use = false; + single_use = false; } else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) { - d.single_use = fixed.is_constant_expression(self.scope); - if (d.single_use == "f") { + 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) { @@ -4690,9 +4694,24 @@ merge(Compressor.prototype, { } } } - if (d.single_use && fixed) { - var value = fixed.optimize(compressor); - return value === fixed ? fixed.clone(true) : value; + if (single_use && fixed) { + var value; + if (d.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) { + value = fixed.clone(true); + var defun_def = value.name.definition(); + value.name = make_node(AST_SymbolLambda, value.name, value.name); + value.name.scope = value; + var lambda_def = value.def_function(value.name); + value.walk(new TreeWalker(function(node) { + if (node instanceof AST_SymbolRef && node.definition() === defun_def) { + node.thedef = lambda_def; + } + })); + } else { + value = fixed.optimize(compressor); + if (value === fixed) value = fixed.clone(true); + } + return value; } if (fixed && d.should_replace === undefined) { var init; diff --git a/lib/scope.js b/lib/scope.js index bbfa037c..bceec289 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -307,7 +307,9 @@ AST_Scope.DEFMETHOD("find_variable", function(name){ }); AST_Scope.DEFMETHOD("def_function", function(symbol){ - this.functions.set(symbol.name, this.def_variable(symbol)); + var def = this.def_variable(symbol); + this.functions.set(symbol.name, def); + return def; }); AST_Scope.DEFMETHOD("def_variable", function(symbol){ -- cgit v1.2.3 title='2023-08-13 02:00:00 +0200'>2023-08-13.guix-authorizations: Authorise Hilton Chain....* .guix-authorizations (hako): Add OpenPGP key fingerprint. Tobias Geerinckx-Rice 2023-06-14.guix-authorizations: Remove Lars-Dominik Braun’s professional key....* .guix-authorizations: Remove from lbraun (professional). Lars-Dominik Braun 2023-05-15.guix-authorizations: Authorize Jorge Gomez....* .guix-authorizations (jgart): Add OpenPGP key fingerprint. Maxim Cournoyer 2023-05-11.guix-authorizations: Authorize Josselin Poiret....* .guix-authorizations (jpoiret): Add OpenPGP key fingerprint. Maxim Cournoyer 2023-05-11.guix-authorizations: Authorize Simon Tournier....* .guix-authorizations (zimoun): Add OpenPGP key fingerprint. Maxim Cournoyer 2023-03-24.guix-authorizations: Remove Paul Garlick due to inactivity....* .guix-authorizations: Remove from pgarlick. Leo Famulari 2023-03-24.guix-authorizations: Remove Jakub Kądziołka due to inactivity....* .guix-authorizations: Remove niedzejkob. Leo Famulari 2023-03-24.guix-authorizations: Remove Chris Marusich due to inactivity....* .guix-authorizations: Remove marusich. Leo Famulari 2023-03-24.guix-authorizations: Remove Brice Waegeneire due to inactivity....* .guix-authorizations: Remove bricewge. Leo Famulari 2023-03-24.guix-authorizations: Remove Alex Kost due to inactivity....* .guix-authorizations: Remove alezost. Leo Famulari 2022-12-11.guix-authorizations: Authorise John Kehayias....* .guix-authorizations (podiki): Add OpenPGP key fingerprint. Tobias Geerinckx-Rice 2022-11-08authorizations: Remove old key for "davexunit"....* .guix-authorizations ("davexunit"): Remove. ("davexunit (2nd)"): Rename to "dthompson". David Thompson 2022-08-11.guix-authorizations: Authorize Andrew Tropin's subkey instead....Addresses <https://issues.guix.gnu.org/57091> for now. * .guix-authorizations (abcdw): Use signing subkey instead of primary. Tobias Geerinckx-Rice 2022-08-05.git-authorizations: Authorize Andrew Tropin....* .git-authorizations (abcdw): Add OpenPGP key fingerprint. Efraim Flashner 2022-01-25.guix-authorizations: Authorize Vinicius Monego....* .guix-authorizations (monego): Add OpenPGP key fingerprint. Maxim Cournoyer 2022-01-03.guix-authorizations: Remove Giovanni Biscuolo due to inactivity....* .guix-authorizations: Remove biscuolo. Leo Famulari 2022-01-03.guix-authorizations: Remove Caleb Ristvedt due to inactivity....* .guix-authorizations: Remove reepca. Leo Famulari 2022-01-03.guix-authorizations: Remove Manolis Fragkiskos Ragkousis due to inactivity....* .guix-authorizations: Remove phant0mas. Leo Famulari 2022-01-03.guix-authorizations: Remove Miguel Ángel Arruga Vivas due to inactivity....* .guix-authorizations: Remove m1gu3l. Leo Famulari 2022-01-03.guix-authorizations: Remove Brian Leung due to inactivity....* .guix-authorizations: Remove leungbk. Leo Famulari 2022-01-03.guix-authorizations: Remove Ivan Petkov due to inactivity....* .guix-authorizations: Remove ipetkov. Leo Famulari 2022-01-03.guix-authorizations: Remove David Wilson due to inactivity....* .guix-authorizations: Remove daviwil. Leo Famulari 2022-01-03.guix-authorizations: Remove Brett Gilio due to inactivity....* .guix-authorizations: Remove brettgilio. Leo Famulari 2022-01-03.guix-authorizations: Remove Amin Bandali due to inactivity....* .guix-authorizations: Remove bandali. Leo Famulari 2022-01-03.guix-authorizations: Remove Alex Sassmannshausen due to inactivity....* .guix-authorizations: Remove atheia. Leo Famulari 2022-01-03.guix-authorizations: Remove Alex Griffin due to inactivity....* .guix-authorizations: Remove ajgrf. Leo Famulari 2022-01-03.guix-authorizations: Remove Gábor Boskovits due to inactivity....* .guix-authorizations: Remove boskovits. Leo Famulari