Если вы посмотрите на диаграмму, которая была на связанном сайте, это может облегчить понимание.
Означает ли это, что все типы в одном процессе имеют один и тот же указатель на один и тот же IVMap?
Да, поскольку он находится на уровне домена, это означает, что все в этом AppDomain имеет одинаковую IVMap.
Как CLR узнает, какую запись выбрать? Выполняется ли линейный поиск для поиска записи, соответствующей текущему типу? Или бинарный поиск? Или какая-то прямая индексация и карта с возможно большим количеством пустых записей в ней?
Классы расположены со смещениями, поэтому у всего есть относительно заданная область, где это должно быть. Это упрощает поиск методов. Он будет искать в таблице IVMap и находить этот метод из интерфейса. Оттуда он переходит в MethodSlotTable и использует реализацию интерфейса этого класса. Карта интерфейса для класса содержит метаданные, однако реализация обрабатывается так же, как и любой другой метод.
Снова с сайта, на который вы указали:
Каждая реализация интерфейса будет иметь запись в IVMap. Если MyInterface1 реализуется двумя классами, в таблице IVMap будет две записи. Запись будет указывать на начало подтаблицы, встроенной в таблицу метода MyClass.
Это означает, что каждый раз, когда интерфейс реализуется, он имеет уникальную запись в IVMap, которая указывает на MethodSlotTable, который, в свою очередь, указывает на реализацию. Таким образом, он знает, какую реализацию выбрать, на основе класса, который ее вызывает, поскольку эта запись IVMap указывает на MethodSlotTable в классе, вызывающем метод. Итак, я полагаю, что это просто линейный поиск по IVMap, чтобы найти правильный экземпляр, а затем они выключены и работают.
РЕДАКТИРОВАТЬ: чтобы предоставить дополнительную информацию о IVMap.
Опять же, по ссылке в OP:
Первые 4 байта первой записи InterfaceInfo указывают на TypeHandle MyInterface1 (см. Рисунок 9 и рисунок 10). Следующее СЛОВО (2 байта) занимают флаги (где 0 наследуется от родителя, а 1 реализуется в текущем классе). СЛОВО сразу после флагов - это начальный слот, который используется загрузчиком классов для размещения подтаблицы реализации интерфейса.
Итак, у нас есть таблица, где число - это смещение байтов. Это всего лишь одна запись в IVMap:
+----------------------------------+
| 0 - InterfaceInfo |
+----------------------------------+
| 4 - Parent |
+----------------------------------+
| 5 - Current Class |
+----------------------------------+
| 6 - Start Slot (2 Bytes) |
+----------------------------------+
Предположим, что в этом домене приложений есть 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, так как я не очень знаком с ним, но я попытался скопировать то, что у них есть в статье, на которую была ссылка.
person
Jetti
schedule
21.03.2012