JavaScriptエンジンのテールコール(TCO)は最適化されていますか?


91

JavaScriptで実装した末尾再帰パスファインディングアルゴリズムがあり、(すべての)ブラウザーでスタックオーバーフロー例外が発生する可能性があるかどうかを知りたいです。


2
それは実際には再帰アルゴリズムですか、それとも再帰で実装された反復アルゴリズムですか?私の理解では、TCOは後者のみを支援することができます。
nmichaels

1
TCOはonly最適化ではないことを付け加えておきます。TCOを備えた1つのインタープリター/コンパイラーに対して作成されたコードは、TCOがないインタープリター/コンパイラーではおそらく機能しないため、それをサポートすることは、コンパイラー/インタープリターではなく、言語仕様の一部である必要があります。
ホフマン

1
あなたは、現在のサポートを参照してください、それがここにKangaxのES6適合表にエンジン全体に進化見ることができます:kangax.github.io/compat-table/es6/...
ロイティンカー

回答:


47

ECMAScript 4仕様はもともとTCOのサポートを追加する予定でしたが、削除されました。

JavaScriptでの末尾呼び出しは不要ですか?

私の知る限り、JavaScriptの広く利用可能な実装では、現在、自動TCOを実行していません。ただし、これは役立つかもしれません。

テールコールの最適化

基本的に、アキュムレータパターンを使用しても同じ効果が得られます。


1
参考までに、Rhinoは「解釈済み」モード(opt = -1)の継続に加えて自動TCOを備えていますwiki.apache.org/cocoon/RhinoWithContinuations
Mark Porter

5
(トローリングについて申し訳ありません)ECMAScript 6には、仕様で適切なテールコールと呼ばれるTCOが含まれています。
凍りつく

@sclv:トランポリン参照とは何ですか?
ブクソール2013年

39
アキュムレータパターンは、TCOと同じ効果を発揮しません。再帰アルゴリズムを末尾再帰形式に変換するだけです。これはTCOを実現するための前提条件ですが、それに代わるものではありません。それでも、末尾呼び出しを最適化しない言語でスタックを爆破します。
Marcelo Cantos 2013年

「現在、広く利用可能なJSの実装では自動TCOを実行しない」これは、正しいフラグを渡した場合、ノード6.2.0の時点で正しくありません
Janus Troelsen

26

現時点では喜びはありませんが、ありがたいことに適切な末尾呼び出しがHarmony(ECMAScriptバージョン6)で予定されてい ますhttp://wiki.ecmascript.org/doku.php?id=harmony:proper_tail_calls


1
@MarkWilbur問題は特にブラウザに関するものであり、ECMAScriptの既存の実装すべてではありません。
役に立たないコード

1
@UselessCodeいいえ、この質問は「Javascriptエンジン」に関するものなので、ブラウザだけではありません
BT

1
@BT確かに多くの非ブラウザJS環境があり、タイトルはより一般的な「Javascriptエンジン」を使用しますが、質問の本文には「...(すべての)ブラウザがスタックを取得する可能性があるかどうかを知りたいですオーバーフロー例外。」
2014

「でもタイトルは……」と対抗しなければなりません。彼は両方に言及しているので、問題は両方についてだと思います。しかし、答えが時代遅れにならないと言っているなら、あなたは正しい。
BT

4
@MarkWilbur私が知っている限り、Chromeと同じバージョンのv8を使用しているノード-現在TCOをサポートしていないため、JSと、現在のV8が生成する最適化されたアセンブラ-gist.github.com/mcfedr / 832e3553964a014621d5
mcfedr

12

あなたが遭遇するほとんどすべてのブラウザは、「あまりにも多くの再帰」に行き詰まります。ここだV8のバグトラッカーのエントリおそらく興味深い読書になります。

それが単純な自己再帰であれば、末尾呼び出しの排除を期待するよりも、明示的な反復を使用する努力に値するでしょう。


バグがようやく受け入れられました。それは叙事詩「機能要求調和」の下にあります。うまくいけば、彼らはそれをV8のES6サポートに追加することを計画していることを意味します。
Txangel 2014年

ここでInternet ExplorerのTCOサポートに投票できます。wpdev.uservoice.com
Roy Tinker

12

末尾呼び出しの最適化は、ECMAScript 6の厳密モードで将来サポートされる予定です。詳細については、http://www.2ality.com/2015/06/tail-call-optimization.htmlを確認してください。

現在のエンジンサポートについては、http://kangax.github.io/compat-table/es6/を確認してください。

現在(2019年7月18日)、次のエンジンがテールコールの最適化をサポートしています。

  • サファリ> = 10
  • iOS> = 10
  • キノマXS6
  • Duktape 2.3

「実験的なJavaScript機能」フラグがオンになっている場合のサポート:

  • ノード6.5
  • Chrome 54 / Opera 41現在のバージョンのcompatテーブルにはもうリストされていません


2

現在、JavaScript実装は末尾再帰を認識していません。ECMAScript 6では変更が加えられており、他の人が言ったように、V8にはオープンチケットがあります。

V8で生成された末尾再帰関数用のアセンブラーを次に示します。

V8が再帰をコンパイルする方法の例

ClangがCで同じ関数をコンパイルした方法と比較してください。

Cコンパイラの末尾再帰の例

V8は再帰呼び出しを保持しますが、Cコンパイラは末尾再帰を認識し、ループに変更しました。


「現在、JS実装は末尾再帰を認識していません。」これはノード6.2.0の時点では正しくありませんが、フラグを渡す必要があります
Janus Troelsen
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.