Спецификация ECMA CLI: описание инструкции initobj для типов значений

#specifications #cil #value-type #intermediate-lan&ua&e

#технические характеристики #cil #тип значения #промежуточный язык

Вопрос:

Спецификация ECMA CLI содержит следующее утверждение в описании initobj инструкции CLI:

«Если typeTok является типом значения, то после выполнения этой инструкции экземпляр готов к вызову метода конструктора».

Однако следующий код на C # (где S является структурой):

 S s = defau<
S s2 = new S();
S s3 = new S(5);
  

компилируется в IL, который выглядит примерно так:

 IL_0001: ldloca.s     s
IL_0003: initobj      S

IL_0009: ldloca.s     s2
IL_000b: initobj      S

IL_0011: ldloca.s     s3
IL_0013: ldc.i4.5
IL_0014: call         instance void S::.ctor(int32)
  

Мой вопрос в том, когда компилятор когда-либо использовал initobj с последующим вызовом конструктора типа значения?

Комментарии:

1. Происходит ли то же самое при использовании других местоположений, помимо локальных переменных? Например, статических полей, полей в экземплярах объектов и т.д… Я спрашиваю, потому что все локальные переменные уже обнулены при запуске метода, по крайней мере, в коде, который создает C #.

2. @JoeSewell Да, похоже, что компилятор обрабатывает поля аналогичным образом: ld[s]flda , initobj

3. Глава II.13.2 важна, обратите внимание, что в ней указано, что инициализация нулем для типов значений не требуется. Таким образом, компилятор C # должен выдать initobj, чтобы получить гарантию. Конструктор не требуется для инициализации всех полей, примером может служить C / CLI. Этого требует C #, поэтому он может опустить initobj.

4. @HansPassant Это имеет смысл. Однако C # использует localsinit флаг, поэтому в контексте моего примера не является ли использование initobj избыточным?

5. Генерация IL компилятором C # вообще не оптимизирована на микроуровне. Задача jitter — превратить это в эффективный машинный код. Она особенно хороша для создания оптимальных типов значений, единственная причина, по которой в .NET была добавлена type system wart, — они хорошо подходят для работы процессора.

Ответ №1:

Если typeTok является типом значения, то после выполнения этой инструкции экземпляр готов к вызову метода конструктора.

Это означает, что конструктор может вызвать конструктор после этой инструкции.

Но, как вы упомянули в комментариях выше, нет необходимости повторно инициализировать локальные файлы перед конструктором из-за localsinit флага в методе si&.

Мой вопрос в том, когда компилятор когда-либо использовал initobj с последующим вызовом конструктора типа значения?

Я могу найти только один случай, когда мне потребуется, чтобы компилятор использовал initobj , скажите ему не использовать localsinit флаг. На данный момент SkipLocalsInitAttribute должен помочь вам воспроизвести случай, но реализация этой функции компилятора еще не началась.