2


0

プロセッサまたはプログラミング言語/コンパイラ、あるいはその両方の機能を再帰する機能はありますか?

関数を再帰的に呼び出す機能は、プロセッサまたはプログラミング言語/コンパイラに固有の機能です。 おそらく、両方とも再帰をサポートする要素が必要ですか?

私は常に、関数を再帰的に呼び出す機能は純粋にプログラミング言語で実装されており、いつ、どこに戻るまでランタイムスタックをレイアウトするかという印象を受けていました。 私はそのように仮定するのは正しいですか、またはプロセッサには再帰を許可する特定のロジックがありますか?

6 Answer


7


プロセッサは、コードが指示する場所にジャンプするだけです。 再帰は間違いなく言語関数です。

コンパイラーが言語を実装する必要がある限り、それはコンパイラー関数でもあります。 しかし、そうでなければ、壊れていると考えます。

最後に、当然、操作の負担はプロセッサにあります。コンテキストと変数をスタックフレームにプッシュし、ルーチンのエントリポイントにジャンプし、命令を実行し、戻る…​ プロセッサが実行する処理です。


5


最新のプロセッサはすべて、関数呼び出しを持ち、スタックベースの命令を返すため、再帰が可能です。

以前のコンピューターは非常に困難な時期でした。 たとえば、IBM 360は、関数の戻り値とローカル変数がコードと並んでいるようにコードをレイアウトしました。 再帰呼び出しは、以前の呼び出しの値を上書きします。


3


言語。

再帰するために常にスタックが必要なわけではありません。 スタックを必要としないタイプの再帰の例については、http://en.wikipedia.org/wiki/Tail_recursion [tail recursion]を参照してください。


1


Carl Smotriczが言ったように、CPUは命令ストリームで発生する分岐命令に従うだけです。 再帰と呼ばれるのは、通常の関数呼び出しよりも_nothing_多いということです。呼び出される関数は、現在実行中の関数と同じであり、高いレベルで非常に興味深い効果があります。


1


スタックアドレッシングモードを備えた最新のプロセッサでも、OS / 360などのシステムで行われていたように、ヒープに呼び出しフレームを割り当てたい場合があります。 たとえば、Schemeでは、継続(基本的に呼び出しフレームとアクティブなローカル変数バインディングの表現)をキャプチャして保持することができます。 関数内のグローバル変数で継続をキャプチャし、その関数から戻ると、アクティブな呼び出しフレームをクリーンアップできません。 ガベージコレクターは、それへの参照がなくなると、ガベージコレクターによってクリーンアップされますが、その間、呼び出しフレームがスタックに割り当てられている場合は、別の場所(ヒープ)にコピーする必要があります。 これは、末尾呼び出しの最適化とは逆のことです。再帰呼び出しにスタックフレームを割り当てる必要がないことを証明できます。 継続するには、呼び出しフレームを割り当て、それとそれに関連する環境を無期限にぶら下げておく必要があります。


1


スタックおよび再帰呼び出しの明示的なハードウェアサポートは必要ありませんが、プロセッサには特定の機能が必要です。 レジスタベースのマシンでは、次のもので十分だと思います。

  • たとえば、次のようにして、保存された値をプログラムカウンターに書き込むことができます。 ジャンプ命令。 これは戻るために必要です。

  • 独自のスタックポインタを格納するレジスタを使い切る余裕があります。

  • 割り込みは物事をひどく混乱させることはありません(おそらくあなたは 割り込みコンテキストにスタックが存在していても存在しません)。

ブートストラップコードは、スタックとして使用するメモリ領域を割り当てる必要があります。

いくつかのプロセッサはこれを提供していません。 ほとんどのプロセッサは、スタックポインターとリンクポインターの明示的なサポート、および標準の呼び出し規約に役立つ命令を備えています。 ただし、独自の呼び出し規約を作成および実装する必要があります。