I motori JavaScript tail call (TCO) sono ottimizzati?


91

Ho un algoritmo di ricerca del percorso ricorsivo di coda che ho implementato in JavaScript e vorrei sapere se alcuni (tutti?) Browser potrebbero ottenere eccezioni di overflow dello stack.


2
È effettivamente un algoritmo ricorsivo o un algoritmo iterativo implementato con la ricorsione? La mia comprensione è che il TCO può aiutare solo con quest'ultimo.
nmichaels

1
Voglio solo aggiungere che il TCO non è onlyun'ottimizzazione. Supportarlo dovrebbe essere parte della specifica del linguaggio, non del compilatore / interprete poiché il codice scritto su un interprete / compilatore con TCO probabilmente non funzionerebbe su un interprete / compilatore senza TCO.
Hoffmann

1
Puoi vedere il supporto attuale e vederlo evolversi tra i motori nella tabella di compatibilità ES6 di Kangax qui: kangax.github.io/compat-table/es6/…
Roy Tinker

Risposte:


47

La specifica ECMAScript 4 originariamente avrebbe aggiunto il supporto per TCO, ma è stata abbandonata:

Niente più chiamate di coda in JavaScript?

Per quanto ne so, nessuna implementazione ampiamente disponibile di JavaScript attualmente fa il TCO automatico. Questo potrebbe esserti utile, però:

Ottimizzazione delle chiamate di coda

In sostanza, utilizzando il modello accumulatore si ottiene lo stesso effetto.


1
Solo per tua informazione, Rhino ha TCO automatico insieme a Continuazioni in modalità "interpretata" (opt = -1) wiki.apache.org/cocoon/RhinoWithContinuations
Mark Porter

5
(scusa per il trolling) ECMAScript 6 ha incluso il TCO, chiamato Proper Tail Calls nelle specifiche.
gelido

@sclv: qual è il riferimento al trampolino?
bukzor

39
Lo schema dell'accumulatore non ha lo stesso effetto del TCO. Trasforma semplicemente algoritmi ricorsivi in ​​forma ricorsiva di coda. Questo è un prerequisito affinché il TCO sia possibile, ma non è un sostituto. Continuerai a saltare lo stack in un linguaggio che non ottimizza le chiamate di coda.
Marcelo Cantos

"nessuna implementazione ampiamente disponibile di JS attualmente esegue il TCO automatico" questo non è corretto a partire dal nodo 6.2.0, se si passa il flag corretto
Janus Troelsen

26

Nessuna gioia per il momento, ma per fortuna sono previste delle chiamate di coda appropriate per Harmony (ECMAScript versione 6) http://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls


1
@MarkWilbur La domanda riguardava specificamente i browser , non tutte le implementazioni esistenti di ECMAScript.
Codice inutile

1
@UselessCode No, questa domanda riguarda i "motori Javascript" quindi ... non solo i browser
BT

1
@BT Ci sono davvero molti ambienti JS non browser, e il titolo usa i più generici "motori Javascript" ma il corpo della domanda specifica "... vorrei sapere se qualche browser (tutti?) Potrebbe ottenere lo stack eccezioni di overflow. "
Codice inutile

Devo controbattere "ma il titolo dice ...". Penso che poiché le menziona entrambe, la domanda riguarda entrambe. Ma hai ragione se dici che non rende la risposta obsoleta.
BT

4
@MarkWilbur Per quanto ne so, il nodo utilizza la stessa versione di v8 di Chrome - che attualmente non supporta il TCO Ho avuto un succo con JS e l'assemblatore ottimizzato che l'attuale V8 produce - gist.github.com/mcfedr / 832e3553964a014621d5
mcfedr

12

Praticamente ogni browser che incontri sbaglierà su "troppa ricorsione". Ecco una voce nel bug tracker V8 che probabilmente sarà una lettura interessante.

Se si tratta di una semplice auto-ricorsione, probabilmente vale la pena utilizzare l'iterazione esplicita piuttosto che sperare nell'eliminazione della chiamata di coda.


Il bug è stato finalmente accettato. È sotto l'epica: "Feature Request Harmony". Si spera che ciò significhi che hanno in programma di aggiungerlo al supporto ES6 in V8.
Txangel

Puoi votare per il supporto TCO in Internet Explorer qui: wpdev.uservoice.com/forums/257854-internet-explorer-platform/…
Roy Tinker

12

In futuro, l'ottimizzazione delle chiamate di coda sarà supportata nella modalità rigorosa di ECMAScript 6. Controlla http://www.2ality.com/2015/06/tail-call-optimization.html per i dettagli.

Controlla http://kangax.github.io/compat-table/es6/ per il supporto del motore corrente.

Al momento (18-07-2019) i seguenti motori supportano l'ottimizzazione della chiamata di coda:

  • Safari> = 10
  • iOS> = 10
  • Kinoma XS6
  • Duktape 2.3

supporto se il flag "funzionalità JavaScript sperimentali" è attivato:

  • Nodo 6.5
  • Chrome 54 / Opera 41 La versione corrente della tabella di compatibilità non la elenca più

3

L'ottimizzazione della chiamata di coda è ora disponibile in LispyScript che compila in JavaScript. Puoi leggere di più al riguardo qui .


E la ricorsione reciproca?
gatto

2

Attualmente nessuna implementazione JavaScript riconosce la ricorsione in coda. Sono state apportate modifiche in ECMAScript 6 e, come altri hanno già detto, c'è un ticket aperto su V8 .

Qui puoi vedere l'assembler generato da V8 per una funzione di ricorsione in coda:

Esempio di come V8 compila la ricorsione

Confrontalo con il modo in cui Clang ha compilato la stessa funzione in C

Esempio di ricorsione della coda del compilatore C.

V8 mantiene la chiamata ricorsiva, mentre il compilatore C ha riconosciuto la ricorsione in coda e l'ha modificata in un ciclo.


"Attualmente nessuna implementazione JS riconosce la ricorsione della coda." non è corretto al Nodo 6.2.0, ma devi passare una bandiera
Janus Troelsen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.