0

(世代別の)ガベージコレクションをコピーすると、あらゆる形式の自動メモリ管理の中で最高のパフォーマンスが得られますが、再配置されたデータのチャンクへのポインターを修正する必要があります。これは、このメモリ管理手法をサポートする言語で、ポインタ演算を禁止し、すべてのポインタが識別可能なオブジェクトの先頭にあることを確認することで有効になります。

JITコンパイラを使用して実行時にコードを生成する場合、コールスタックのリターンアドレスはコードブロックの先頭ではなく、コードブロック内のランダムな場所を指すため、少し注意が必要です。修正が問題になります。

これは通常どのように解決されますか?

4

1 に答える 1

1

多くの場合、コードを再配置しません。これは、スタックや他のアドレスを修正するのが実際に複雑であるため(コードフラグメントを飛び越えると考えてください)、そのようなコードのガベージコレクションを実際に必要としないためです(とにかく作成したコードによってのみ操作されるため、手動メモリ管理を行うことができます)。また、(アプリケーションオブジェクトと比較して)大量のマシンコードを作成することは期待できないため、断片化などは問題になりません。

マシンコードを移動してスタックを修正することを主張する場合、次の方法があると思います。Mark-Compactと同様に、「ブレークテーブル」を作成します(この名前の由来はわかりません。「再配置テーブル」は次のようになります。より明確に)移動したオブジェクトへのポインタを調整する必要がある量を示します。ここで、スタックを調べてリターンアドレス(もちろん、プラットフォーム固有です)を探し、再配置されたコードを参照している場合は修正します。完全に一致するものを探す代わりに、現在置き換えている差出人住所よりも低い最高の住所を検索します。このアドレスが実際にオブジェクトのサイズを調べることで移動したマシンコードを参照していることを確認できます(結局のところ、オブジェクトの先頭へのポインタがあります)。このアプローチは、さまざまな理由から、すべてのオブジェクトに対して実行可能ではありません。

しかし、同様のことをする理由は他にもあります。一部のJITコンパイラは、オンスタック置換を備えています。これは、一部のマシンコードの新しいバージョン(たとえば、より最適化された、またはより最適化されていない)を作成し、古いバージョンのすべてのオカレンスをそれで置き換えることを意味します。ただし、これは単に差出人住所を修正するよりもはるかに複雑です。古いバージョンがぶら下がっていた場所で、新しいバージョンが論理的に継続することを確認する必要があります。これがどのように実装されているかはよくわからないので、詳しくは説明しません。

于 2013-03-19T19:19:09.680 に答える