Если вы посмотрите на диаграмму, которая была на связанном сайте, это может облегчить понимание.
Означает ли это, что все типы в одном и том же процессе имеют одинаковый указатель на один и тот же IVMap?
Да, поскольку он находится на уровне домена, это означает, что все в этом AppDomain имеет тот же IVMap.
Как CLR узнает, какую запись выбрать? Делает ли он линейный поиск, чтобы найти запись, которая соответствует текущему типу? Или бинарный поиск? Или какая-то прямая индексация и карта с большим количеством пустых записей?
Классы размечены со смещением, поэтому все имеет относительно установленную область, где это было бы. Это облегчает поиск методов. Он будет искать в таблице IVMap и находить этот метод из интерфейса. Оттуда он переходит к MethodSlotTable и использует реализацию интерфейса этого класса. Карта интерфейса для класса содержит метаданные, однако реализация обрабатывается так же, как и любой другой метод.
Снова с сайта, на который вы ссылались:
Каждая реализация интерфейса будет иметь запись в IVMap. Если MyInterface1 реализован двумя классами, в таблице IVMap будет две записи. Запись будет указывать на начало вложенной таблицы, встроенной в таблицу методов MyClass
Это означает, что каждый раз, когда интерфейс реализован, он имеет уникальную запись в IVMap, которая указывает на MethodSlotTable, который, в свою очередь, указывает на реализацию. Таким образом, он знает, какую реализацию выбрать, основываясь на классе, который его вызывает, так как эта запись IVMap указывает на MethodSlotTable в классе, вызывающем метод. Так что я представляю, что это просто линейный поиск в IVMap, чтобы найти правильный экземпляр, а затем они выключены и работают.
РЕДАКТИРОВАТЬ: Чтобы получить больше информации о IVMap.
Снова по ссылке в ОП:
Первые 4 байта первого входа InterfaceInfo указывают на TypeHandle MyInterface1 (см. Рисунок 9 и рисунок 10). Следующее WORD (2 байта) занято Flags (где 0 наследуется от родителя, а 1 реализуется в текущем классе). WORD сразу после Flags - это Start Slot, который используется загрузчиком классов для размещения вложенной таблицы реализации интерфейса.
Итак, у нас есть таблица, где число - это смещение байтов. Это всего лишь одна запись в IVMap:
+----------------------------------+
| 0 - InterfaceInfo |
+----------------------------------+
| 4 - Parent |
+----------------------------------+
| 5 - Current Class |
+----------------------------------+
| 6 - Start Slot (2 Bytes) |
+----------------------------------+
Предположим, в этом AppDomain имеется 100 интерфейсных записей, и нам нужно найти реализацию для каждой из них. Мы просто сравниваем 5-й байт, чтобы увидеть, соответствует ли он нашему текущему классу, и если это так, мы переходим к коду в 6-м байте. Поскольку каждая запись имеет длину 8 байт, нам нужно сделать что-то вроде этого: (Psuedocode)
findclass :
if (!position == class)
findclass adjust offset by 8 and try again
Хотя это все еще линейный поиск, на самом деле это не займет так много времени, пока размер итерируемых данных невелик. Надеюсь, это поможет.
РЕДАКТИРОВАТЬ2:
Итак, взглянув на диаграмму и спросив, почему в IVMap нет слота 1 для класса на диаграмме, я перечитал раздел и обнаружил:
IVMap создается на основе информации карты интерфейса, встроенной в таблицу методов. Карта интерфейса создается на основе метаданных класса в процессе компоновки MethodTable. После завершения загрузки типов в диспетчеризации методов используется только IVMap.
Таким образом, IVMap для класса загружается только с интерфейсами, которые наследует определенный класс. Похоже, что он копирует из домена IVMap, но сохраняет только те интерфейсы, на которые указывают. Это поднимает другой вопрос, как? Скорее всего, это эквивалентно тому, как C ++ делает vtables, где каждая запись имеет смещение, а карта интерфейса предоставляет список смещений для включения в IVMap.
Если мы посмотрим на IVMap, который может быть для всего этого домена:
+-------------------------+
| Slot 1 - YourInterface |
+-------------------------+
| Slot 2 - MyInterface |
+-------------------------+
| Slot 3 - MyInterface2 |
+-------------------------+
| Slot 4 - YourInterface2 |
+-------------------------+
Предположим, что в этом домене есть только 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, так как я не знаком с ним, но я попытался скопировать то, что у них есть встатья, которая была связана с.