14

正確なガベージ コレクションを実装する場合、スタック上のどのワードがポインターであり、どのワードが整数や浮動小数点数などの他の種類のデータであるかを把握するという問題が常に発生します。解釈された言語は通常、すべてをポインターにすることでこの問題を解決します。Lisp などの一部の言語のコンパイラは、通常、タグ ビットを使用してポインタと整数を区別することで解決します。

しかし、ボックス化されていない機械語整数と浮動小数点数を完全にサポートする Java や C# などの言語用の JIT コンパイラはどうでしょうか? スタックと CPU レジスタの内容のどれがポインタであるかをどのように判断するのでしょうか?

4

2 に答える 2

10

このような言語のバイトコードには、常に完全な型情報が含まれています。これは、メタデータ (引数の型など) に格納されるか、またはオペコードに暗黙的に格納されます (たとえば、整数または浮動小数点数を追加するための異なるオペコードが存在する場合があります)。

コードを最適化するとき、コンパイラはこの情報にアクセスし、それを使用して最適化を改善できます。また、この情報を使用して、特定のGC セーフ ポイントでコンパイルされたコードのメタ データを生成します。

GC セーフ ポイントはコード内の場所であり、スレッドを中断して別のスレッドをスケジュールしたり、ガベージ コレクションを実行したりしても安全です。GC セーフ ポイントでは、必要なメタ データを使用して、どのレジスタにポインタが含まれていてどのレジスタに含まれていないかを確認できます。たとえば、Hotspot JVM では、ループには常にメモリ内の特別な場所からの読み取りが含まれます。その読み取りの結果は使用されませんが、命令が読み取るアドレスが読み取り保護されている場合、ページ フォールトが発生します。これを使用して、そのページを読み取り専用に設定するだけで、任意の時点でスレッドを中断できます。スレッドが中断されると、プログラム カウンターを調べて、ハッシュ テーブルなどのメタ データを調べます。

GC セーフ ポイントにする必要があるその他の場所は、割り当てサイトです。割り当てが失敗し、GC が発生する可能性があります。一度に複数のオブジェクトにメモリを割り当てることで、セーフ ポイントの数を減らすことができます。

編集:GCセーフポイントの使用は、多くのオプションの1つにすぎないことに注意してください。SK ロジックが述べたように、別のオプションは、ポインターと非ポインターに別々のスタックを使用することです。GC 中に 1 つのスタックのすべての要素をトラバースする必要があるが、他の要素はトラバースしないことは明らかです。ただし、レジスタ内のポインターには注意する必要があります。たとえば、レジ​​スタにライブ ポインターがある場合は常に、同じポインターがスタックにも存在する必要があります。

3 番目のオプションは、実際のスタック上に存在するスタック ルートへのポインターのリンク リストを含むシャドウ スタックを使用することです。詳細については、Fergus Henderson による論文「Accurate Garbage Collection in an Uncooperative Environment」(PDF)を参照してください。

于 2011-09-11T15:36:38.000 に答える
0

Java や C# などの言語は、正確なコレクションを必要としないように指定されています。実装では保守的なコレクターを使用する場合があり、ポインターのように見えるビットのパターンがポインターのように扱われます (ただし、実際には整数または浮動小数である可能性があります)。たとえば、Boehm コレクターは、JIT 言語に使用できる保守的なコレクターです。

于 2011-08-17T23:41:26.680 に答える