Next: Up: Previous:

レジスタ使用慣例

プロセッサのためのレジスタ使用慣例は CPU レジスタを二つの カテゴリに分類する. 一つは caller が手続きをまたがって 保存されることを仮定しているcallee-save registerであり, もう一つは caller が手続き呼び出しをまたがると 破壊されることを仮定しているcaller-save registerである. 手続きが正しいレジスタの状態で正しい位置にリターンするために, スタックフレームはリターンアドレス, 親のフレームポインタ, それが破壊したcallee-save registerをセーブする. 手続きが リターンするときには, それはフレームポインタ, スタックポインタ, callee-save registerの値を回復し, リターンアドレスにジャンプする. その後callerは, FP,SP,callee-save registerが元のままの 値を持っており, 他のレジスタは持っていないことを 仮定して実行を続ける.

Callee-save registerの存在は我々のスレッド実装の 中の最も問題となる部分である. なぜなら手続きのコンテキストが未知の数のフレームや レジスタに広がるかもしれないからである. 手続き f が4つの callee-save register{A,B.C.D} を 使用しているとし, f は {A,B}を使用する手続き g を呼びだし, さらに g が今度は callee-save register{B,C} を 使う手続き h を呼び出すとしよう. f に関連するコンテキストは 何だろうか? h がアクティブ(例えば, そのフレームがスタックの 頭にある)の時は, ABg のスタックフレームに セーブされ, Ch のスタックフレームにセーブされ, そして, D はまだレジスタの上にある! f のコンテキストを保存し, 後で回復するためには, それらが どこにあるかがわからなくてはならない.

どのcallee-save registerが手続きによって 使われていて, どこにそれらが保存されているかの 情報はスタックフレームには存在しない. もしそれがあったとしても, 情報を解釈し, それらを回復することはコンテキストスイッチを 非常に遅くする. 代わりに, 我々がcallee-save registerを扱う方式は, Cコンパイラのコード生成方式の仮定に依存している. 仮定されるCコンパイラのコード生成スタイルでは, 手続きは callee-save registerを手続きのentry(prologue)で すべて一度に保存し, exit(epilogue)ですべて一度に回復する. 言い換えれば, 手続きは実行パスにしたがってそれらを インクリメンタルに保存する, ということをしない. その仮定は我々が知っている GNU C コンパイラを含む 全てのコンパイラで当てはまる. Mipsのプログラマーズ マニュアル [29] は, callee-save registerが entryでセーブされることを明示的に述べている. この仮定は, スレッドをブロックさせ, 一貫した状態で 親を再開させるepilogue code threadingと 呼ばれる, 3.2.4 (3)節で さらに説明される興味深い技法を有効にする.



Mitsubishi Research Institute,Inc.
Mon Feb 24 19:27:36 JST 1997