next up previous contents index
Next: ヒープの使い方 Up: KLICの基本的な動作 Previous: データのキャッシュ

  
例外的な処理

 

KLICでは、基本的に、先([*]ページ、第3.1章参照)に述べた動作モデルのように、 KL1で書かれたコードを実行しつづける。しかしながら、 以下に記述するような理由により、「例外的な処理」を行う必要が生じるときがある。

これらの「例外的処理」は必要に応じて、「述語実行の切れ目」で 行う。つまり、1つの述語が終了し、次の述語を実行する間に 例外的処理を行う必要があるかどうかを判断し、もし必要であれば、 必要な処理(例えば、GC)を行う。

KLICでは、1つのゴールのリダクション途中では、 様々な変数(一時変数, 引数変数、ヒープ割付点などなど) が更新された状態にあり、GC等を含み得るような処理をするために 必要なこうした変数の退避は難しく、効率も悪いため、 述語の実行中は「他の処理」([*]ページ、第3.2章参照) を行わず、述語実行に専念するようにしている。

よって、述語実行中に 「例外的処理」が必要になった場合には(例えば、割り込みハンドラで) 「次の述語実行の切れ目でわかるように」覚えておくだけで、すぐに通常の 述語実行を継続する。そして述語実行の切れ目では、「例外的処理」を行う必要が あるかどうか検出し、必要あれば、他の処理を行う。

この「例外的処理」要求の検出が、allocpとheaplimitの比較である。 allocpはヒープ割付点であり、heaplimitは、ヒープの上限である。 つまり、通常のヒープ溢れはこの比較で検出され、GCが起動される。 他の「割り込み」については、人為的(一時的)にこのheaplimitを0にすることにより 割込まれたことを記憶しておく、という方式をとっている。 したがって、この大小比較のみで、「例外的処理」要求有無の検出ができる。

この例外処理は、モジュール関数の末尾で呼び出される実行時ライブラリ、 interrupt_goal で行われる。この内部ではreasonpの値により、 どのような例外が起きたのか判定され、適切な処理が行われる。 これらの処理をひきおこすコード箇所については、第3.2章 ([*]ページ)を 参照のこと。 

他にすべき処理が生じた時:
この場合には、reasonp には 0が セットされている。 この場合には、resumed_goals にgoalを格納し、 他の処理をすべくreturnする。

述語が「失敗」したとき:
この場合には中断スタックポインタは 中断スタックの底を 指している。 失敗の処理(関数do_fail())が呼び出される。

述語が「中断」しそうなとき:
これまでの説明で判明したように、KLICでは、3段以上REFの連鎖がある場合には コンパイルコード中では追跡をあきらめ、interrupt_goal の呼び出しを行って いる。これは、通常それほど長いREF鎖はあまりないこと。 その結果、コンパイルコード量が 増加するわりには、実行速度向上がないことに起因している。

この場合には、「中断原因の候補」は中断スタックに積まれているので、 それを調べ、候補が全て真に未定義変数(含む中断構造)であれば中断処理を行う。 候補のいずれかが具体値であることが判明すれば、resume_same_prio()関数 により、当該ゴールを「再開」する(つまり、エンキューしてしまう)。



 

Sekita Daigo
1998-05-18