Рабочим названием платформы .NET было |
Язык CIL: инструкции для поддержки объектной модели
Язык CIL, в отличие от большинства других ассемблерных языков, содержит богатый набор инструкций, предназначенных для поддержки объектной модели. Этот набор можно разделить на четыре основные категории:
- инструкции для работы с объектами;
- инструкции для работы с массивами;
- инструкции для работы с типами-значениями;
- инструкции для работы с типизированными ссылками.
Инструкции для работы с объектами
Инструкции для работы с объектами - это базовые инструкции для поддержки объектно-ориентированной парадигмы.
Создание объектов
Инструкция newobj (см. таблицу 3.25) выполняет выделение памяти для объекта в куче и затем вызывает для этого объекта конструктор. Операции выделения памяти и вызова конструктора объединены в одной инструкции не случайно, так как это гарантирует отсутствие в куче неинициализированных объектов.
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x73 | newobj | token | Создает новый объект и вызывает для него конструктор |
Токен метаданных, находящийся во встроенном операнде инструкции, указывает на описатель конструктора в таблицах метаданных. Тип создаваемого объекта определяется через информацию о конструкторе (это тот класс, внутри которого объявлен конструктор).
Диаграмма стека для инструкции newobj:
... , arg1, ... , argN -> ... , obj
Инструкция newobj потребляет со стека вычислений параметры конструктора и оставляет на стеке ссылку на созданный объект. Параметры вызываемого конструктора должны быть расположены в стеке слева направо, то есть сначала на стек должен быть загружен первый аргумент, затем второй и т.д.
Хотя первым (неявным) параметром для любого конструктора является ссылка на инициализируемый объект (параметр this ), перед вызовом инструкции newobj этот параметр не должен загружаться на стек вычислений. Дело в том, что ссылка на объект формируется в процессе выполнения инструкции (после выделения памяти в куче и до вызова конструктора) и затем автоматически передается конструктору. Происходит как бы "подкладывание" ссылки this под другие параметры конструктора на стеке вычислений.
Особый случай применения инструкции newobj связан с созданием экземпляров типов-значений на стеке вычислений. Если указанный во встроенном операнде конструктор принадлежит типу-значению, то новый экземпляр этого типа создается не в куче, а прямо на стеке вычислений.
Проверка типа объекта
В таблице 3.26 приведены две инструкции, осуществляющие проверку типа объекта, ссылка на который лежит на вершине стека вычислений. Токен метаданных, находящийся во встроенном операнде инструкции, указывает на описатель типа в таблицах метаданных.
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x74 | castclass | token | Проверяет, соответствует ли тип объекта на вершине стека. В случае несоответствия генерирует исключение InvalidCastException |
0x75 | isinst | token | Проверяет, соответствует ли тип объекта на вершине стека. Если соответствует, то оставляет объект на стеке, в противном случае заменяет объект на null |
Диаграмма стека для инструкций проверки типа объекта:
... , obj -> ... , obj
Через инструкции проверки типа объекта реализуются операции приведения типов в языках высокого уровня.
Работа с полями объектов
В таблице 3.27 приведены инструкции, которые загружают на стек вычислений значения и адреса полей объектов, а также сохраняют значения со стека в полях объектов. Токены метаданных во встроенных операндах инструкций указывают на информацию о нужном поле.
Вызов виртуальных методов
Инструкция callvirt (см. таблицу 3.28) отличается от инструкции call главным образом тем, что адрес вызываемого метода определяется во время выполнения программы путем анализа типа объекта, для которого вызывается метод. Тем самым реализуется идея позднего связывания, необходимая для поддержки полиморфизма.
Диаграмма стека для инструкции callvirt:
... , obj, arg1, ... , argN -> ... , retVal
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x6F | callvirt | token | Вызов метода с использованием позднего связывания |
Токен метаданных, находящийся во встроенном операнде инструкции, указывает на информацию о вызываемом методе в таблицах метаданных (имя метода, класс и сигнатура). Определение метода, который нужно вызвать, происходит следующим образом. Система выполнения анализирует класс объекта, для которого вызывается метод (на диаграмме стека этот объект обозначен как obj ), выполняя поиск принадлежащего этому классу экземплярного метода, имеющего нужные имя и сигнатуру. Если такой метод отсутствует, аналогичный поиск производится по порядку на всей цепочке суперклассов, от которых наследует класс объекта. Если в результате метод не будет найден, то генерируется исключение MissingMethodException, но эта ситуация невозможна в верифицированном коде.
Загрузка строковых констант
Для загрузки на стек вычислений строковых констант предусмотрена отдельная инструкция ldstr, приведенная в таблице 3.29. Токен, находящийся во встроенном операнде инструкции, указывает на образ строки в куче пользовательских строк, находящейся в составе метаданных. Инструкция создает объект класса System.String, копирует в него образ строки и оставляет ссылку на созданный объект на вершине стека вычислений.
Код | Инструкция | Встроенный операнд | Описание |
---|---|---|---|
0x72 | ldstr | token | Создает на вершине стека объект-строку |
Диаграмма стека для инструкции ldstr:
... -> ... , obj