
リンク先にあった図を見ていただくと分かりやすいかもしれません。
これは、同じプロセス内のすべてのタイプが同じ IVMap への同じポインターを持っているということですか?
はい、ドメイン レベルであるため、その AppDomain 内のすべてが同じ IVMap を持つことを意味します。
CLR はどのエントリを選択するかをどのように判断しますか? 現在のタイプに一致するエントリを見つけるために線形検索を行いますか? それとも二分探索?または、ある種の直接索引付けで、おそらく多くの空のエントリが含まれるマップがありますか?
クラスはオフセットでレイアウトされているため、すべてのクラスが相対的に設定された場所に設定されています。これにより、メソッドを探すときの作業が容易になります。IVMap テーブルを検索し、インターフェイスからそのメソッドを見つけます。そこから MethodSlotTable に移動し、そのクラスのインターフェイスの実装を使用します。クラスのインターフェイス マップはメタデータを保持しますが、実装は他のメソッドと同様に扱われます。
リンクしたサイトからもう一度:
各インターフェイスの実装には、IVMap のエントリがあります。MyInterface1 が 2 つのクラスによって実装されている場合、IVMap テーブルには 2 つのエントリがあります。エントリは、MyClass メソッド テーブル内に埋め込まれたサブテーブルの先頭を指します。
これは、インターフェースが実装されるたびに、IVMap に固有のレコードがあり、これが MethodSlotTable をポイントし、それが実装をポイントすることを意味します。そのため、その IVMap レコードがメソッドを呼び出しているクラスの MethodSlotTable を指しているため、それを呼び出しているクラスに基づいて選択する実装を認識します。したがって、正しいインスタンスを見つけるために IVMap を線形検索するだけで、それらはオフになって実行されていると思います。
編集: IVMap に関する詳細情報を提供します。
繰り返しますが、OP のリンクから:
最初の InterfaceInfo エントリの最初の 4 バイトは、MyInterface1 の TypeHandle を指しています (図 9 および図 10 を参照)。次の WORD (2 バイト) はフラグによって使用されます (0 は親から継承され、1 は現在のクラスで実装されます)。Flags の直後の WORD は Start Slot で、クラス ローダーがインターフェイス実装サブテーブルを配置するために使用します。
ここに、数値がバイトのオフセットであるテーブルがあります。これは、IVMap 内の 1 つのレコードにすぎません。
+----------------------------------+
| 0 - InterfaceInfo |
+----------------------------------+
| 4 - Parent |
+----------------------------------+
| 5 - Current Class |
+----------------------------------+
| 6 - Start Slot (2 Bytes) |
+----------------------------------+
この AppDomain に 100 個のインターフェイス レコードがあり、それぞれの実装を見つける必要があるとします。5 番目のバイトを比較して現在のクラスと一致するかどうかを確認し、一致する場合は 6 バイト目のコードにジャンプします。各レコードの長さは 8 バイトなので、次のようにする必要があります: (疑似コード)
findclass :
if (!position == class)
findclass adjust offset by 8 and try again
これは依然として線形検索ですが、実際には、反復されるデータのサイズがそれほど大きくないため、それほど時間はかかりません。それが役立つことを願っています。
EDIT2:
ダイアグラムを見て、ダイアグラム内のクラスの IVMap にスロット 1 がない理由を疑問に思った後、セクションを読み直したところ、次のことがわかりました。
IVMap は、メソッド テーブル内に埋め込まれた Interface Map 情報に基づいて作成されます。インターフェイス マップは、MethodTable レイアウト プロセス中にクラスのメタデータに基づいて作成されます。タイプロードが完了すると、IVMap のみがメソッドのディスパッチに使用されます。
そのため、クラスの IVMap は、特定のクラスが継承するインターフェースのみでロードされます。Domain IVMap からコピーしているように見えますが、ポイントされているインターフェースのみを保持しています。これは別の質問を引き起こします。おそらく、C++ が各エントリにオフセットを持ち、Interface Map が IVMap に含めるオフセットのリストを提供する vtables を行う方法と同等です。
このドメイン全体の可能性がある IVMap を見ると、次のようになります。
+-------------------------+
| Slot 1 - YourInterface |
+-------------------------+
| Slot 2 - MyInterface |
+-------------------------+
| Slot 3 - MyInterface2 |
+-------------------------+
| Slot 4 - YourInterface2 |
+-------------------------+
このドメインには Interface Map の実装が 4 つしかないとします。各スロットにはオフセットがあり (前に投稿した IVMap レコードと同様)、このクラスの IVMap はこれらのオフセットを使用して IVMap 内のレコードにアクセスします。
各スロットが 8 バイトで、スロット 1 が 0 から始まると仮定すると、スロット 2 と 3 を取得したい場合は、次のようにします。
mov ecx,edi
mov eax, dword ptr [ecx]
mov eax, dword ptr [ecx+08h] ; slot 2
; do stuff with slot 2
mov eax, dword ptr [ecx+10h] ; slot 3
; do stuff with slot 3
x86 については詳しくないので、申し訳ありませんが、リンク先の記事にあるものをコピーしようとしました。