このような言語のバイトコードには、常に完全な型情報が含まれています。これは、メタデータ (引数の型など) に格納されるか、またはオペコードに暗黙的に格納されます (たとえば、整数または浮動小数点数を追加するための異なるオペコードが存在する場合があります)。
コードを最適化するとき、コンパイラはこの情報にアクセスし、それを使用して最適化を改善できます。また、この情報を使用して、特定のGC セーフ ポイントでコンパイルされたコードのメタ データを生成します。
GC セーフ ポイントはコード内の場所であり、スレッドを中断して別のスレッドをスケジュールしたり、ガベージ コレクションを実行したりしても安全です。GC セーフ ポイントでは、必要なメタ データを使用して、どのレジスタにポインタが含まれていてどのレジスタに含まれていないかを確認できます。たとえば、Hotspot JVM では、ループには常にメモリ内の特別な場所からの読み取りが含まれます。その読み取りの結果は使用されませんが、命令が読み取るアドレスが読み取り保護されている場合、ページ フォールトが発生します。これを使用して、そのページを読み取り専用に設定するだけで、任意の時点でスレッドを中断できます。スレッドが中断されると、プログラム カウンターを調べて、ハッシュ テーブルなどのメタ データを調べます。
GC セーフ ポイントにする必要があるその他の場所は、割り当てサイトです。割り当てが失敗し、GC が発生する可能性があります。一度に複数のオブジェクトにメモリを割り当てることで、セーフ ポイントの数を減らすことができます。
編集:GCセーフポイントの使用は、多くのオプションの1つにすぎないことに注意してください。SK ロジックが述べたように、別のオプションは、ポインターと非ポインターに別々のスタックを使用することです。GC 中に 1 つのスタックのすべての要素をトラバースする必要があるが、他の要素はトラバースしないことは明らかです。ただし、レジスタ内のポインターには注意する必要があります。たとえば、レジスタにライブ ポインターがある場合は常に、同じポインターがスタックにも存在する必要があります。
3 番目のオプションは、実際のスタック上に存在するスタック ルートへのポインターのリンク リストを含むシャドウ スタックを使用することです。詳細については、Fergus Henderson による論文「Accurate Garbage Collection in an Uncooperative Environment」(PDF)を参照してください。