[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

17.9 入れ子関数のトランポリン

トランポリン(trampoline)は、小さなコード断片であり、入れ子 関数のアドレスを取るコードがあると、実行時に作成される。 普通はにスタックに置かれる。これは、入れ子関数を含んでいる関数の スタックフレームの中になる。 以下に説明するマクロは、トランポリンを確保したり、初期化するコードを 生成する方法を GNU CC に知らせる。

トランポリン中の命令群は次の二つの作業を行なう必要がある。 ある定数アドレスを静的チェーンレジスタにロードすること、および ネストした関数の実際のアドレスにジャンプすることである。 m68k のような CISC マシンでは、このような場合二つの命令、つまり、 一個の即値の移動命令と一個のジャンプ命令が必要である。 そうすると、この二つのアドレスはトランポリン中ではワード長の即値オペランド として存在する。RISC マシンでは、各アドレスを一個のレジスタにロードするのに 二つの部分に分けて行なう必要があるものが多い。各アドレスの断片は、 別々の即値オペランドを形成する。

トランポリンを初期化するために生成されたコードは、可変部分を命令の 即値オペランドに格納しなければならない。可変部分とは、静的チェーンと 関数のアドレスである。CISC の機種では、これは単に、各アドレスを トランポリンの先頭から適切なオフセットの地点のメモリ参照へコピーする という問題になる。RISC の機種では、アドレスの各断片を取りだして、 別々にストアする必要がでてくる可能性がある。

TRAMPOLINE_TEMPLATE (file)

一個の C の文。この文は、ストリーム file に、あるトランポリンの 固定部分を含むデータブロック用のアセンブラコードを出力する。 このコードにはラベルを含めてはならない。ラベルの面倒は自動的にみてくれる。

このマクロを定義しないということは、ターゲットがテンプレートを必要と しないということを意味する。トランポリンを決められた場所にコピーする ブロック移動コードの大きさが、その場でトランポリンを生成するコードの 大きさよりも大きいシステムではこのマクロを定義しないこと。

TRAMPOLINE_SECTION

サブルーチン名。このサブルーチンは、トランポリンのテンプレートを 置くべきセクションへの切替えを行なう(see section 出力をセクション(text, data, …)に分割する)。 デフォルトは ‘readonly_data_section’ の値であり、 その場合、読み出し専用データを入れるセクションにトランポリンが置かれる。

TRAMPOLINE_SIZE

整数値を取るC の式であり、トランポリンのバイト単位での大きさを表す。

TRAMPOLINE_ALIGNMENT

トランポリンに必要なアラインメントをビット数で表す。

このマクロが定義されていないと、BIGGEST_ALIGNMENT の値が トランポリンのアラインメントとして使われる。

INITIALIZE_TRAMPOLINE (addr, fnaddr, static_chain)

トランポリンの可変部分を初期化する C の文。 addr は、トランポリンのアドレスの RTX である。 fnaddr は、ネスト関数のアドレスの RTX である。 static_chain は、関数が呼ばれたときにその関数に渡すべき 静的チェーン値を表す RTX である。

ALLOCATE_TRAMPOLINE (fp)

トランポリン用の実行時スペースを確保する C の式。 この式の値は、トランポリンのスペースへのメモリ参照を表す RTX とすべきである。

このマクロが定義されていない場合は、デフォルトでトランポリンは スタックスロットとして確保される。ほとんどの機種ではこのデフォルトが 正しい。例外となる機種は、スタック領域にある命令を実行することが不可能な 機種である。そのような機種では、別のスタックを独立に実装しなければ ならない可能性がある。その場合は、このマクロを FUNCTION_PROLOGUEFUNCTION_EPILOGUE を一緒に使って行なう。

fp は、あるデータ構造、struct function を指す。 この構造体は、トランポリンが必要になる関数を含む関数(包含関数)の コンパイル状況を記述する。 普通(ALLOCATE_TRAMPOLINE が定義されてないとき)、トランポリン用の スタックスロットはこの包含関数のスタックフレーム内にある。 その他の割当戦略を取った場合も、この情報に類似したものを行なわなければ ならない。

多くの機種ではトランポリンを実装するのは困難である。命令とデータで 別々のキャッシュを持っているからである。スタック位置へ書き込んでも 命令キャッシュにあるメモリ内容をクリアしないので、プログラムが その位置にジャンプしたとき、古い内容を実行してしまう。

二つの解決方法がある。一つは、トランポリンが設定されたら常に 命令キャッシュの関係する部分をクリアすることである。 もう一つは、全てのトランポリンを、ある標準のサブルーチンにジャンプさせる ことにより、同じものにしてしまうことである。 前者の方法はトランポリンの実行が速くなり、後者は初期化が速くなる。

トランポリンが初期化されるとき命令キャッシュをクリアするには、 キャッシュの形状を記述する以下のマクロを定義する。

INSN_CACHE_SIZE

キャッシュの合計サイズをバイト単位で表す。

INSN_CACHE_LINE_WIDTH

キャッシュの各ラインの長さをバイト数で表す。キャッシュは分離したスロットで ある複数のキャッシュ・ラインからなる。各キャッシュ・ラインは、 メモリから取り出した、ある連続なデータの塊を保持する。 データがキャッシュに持ち込まれる度に、一本のライン全体が一度に読み込まれる。 あるキャッシュ・ラインにロードされたデータは、常に、ラインの大きさに 等しい境界に整列する。

INSN_CACHE_DEPTH

任意の特定のメモリ位置を保持できる別のキャッシュラインの数。

あるいは、命令キャッシュを直接クリアするシステムコールまたは命令が ある機種では、以下のマクロを定義することができる。

CLEAR_INSN_CACHE (BEG, END)

一個の C の式。定義されていれば、この式は、指定された間隔で 命令キャッシュをクリアする。このマクロが定義されておらず、 マクロ INSN_CACHE_SIZE が定義されていると、ある汎用のコードが 生成され、キャッシュをクリアする。このマクロの定義は普通、 一連の asm 文となるだろう。BEGEND は どちらもポインタ式である。

標準のサブルーチンを使うには、以下のマクロを定義する。 さらに、トランポリンの中の命令が、あるキャッシュライン全体を全く 同一の命令で埋め尽くすこと、あるいはトランポリンコードの先頭が常に そのキャッシュラインの同じ場所に整列することを保証しなければならない。 ‘m68k.h’ を指針として読んで欲しい。

TRANSFER_FROM_TRAMPOLINE

トランポリンがその仕事を行なうために特別なサブルーチンを必要とする時は このマクロを定義する。このマクロは、GNU CC によりコンパイルされる asm 文の連なりに展開される必要がある。 展開されると、ライブラリ関数 __transfer_from_trampoline に入る。

あるコンパイル済みの C の関数の通常のプロローグコードを、そのサブルーチンに ジャンプするときには、実行するのを避ける必要がある場合は、アセンブラコード の中に特別なラベルを置くことで行なうことができる。asm 文を 一個使ってアセンブララベルを生成し、もう一個の asm 文でその ラベルをグローバルにする。そうしておくと、トランポリンがそのラベルを 使って、その特別なアセンブラコードに直接ジャンプすることができる。


This document was generated using texi2html 1.78.