.NET MSIL: как команды определяют размер операндов?

В MSIL есть единственная команда add для добавления двух аргументов (извлекать из стека, добавлять, помещать в стек). Как он узнает, должен ли он извлечь 2 байта, 4 или 8 байтов?

В java разные байт-коды (fadd, dadd, iadd,...), но как они справляются с этим в .NET?


person Mahdi    schedule 27.07.2016    source источник


Ответы (3)


Байт-код Java был оптимизирован для выполнения интерпретатором, ранние JVM еще не имели Hotspot. .NET msil с самого первого дня разрабатывался так, чтобы всегда можно было использовать джиттинг, никаких специальных кодов операций для разных типов операндов не требовалось.

Джиттер знает тип операнда из состояния стека. Какой бы код операции не помещал значение в стек, он также указывает тип. Скажем, Opcodes.Ldarg_0, джиттер знает тип из сигнатуры метода. Отслеживание состояния стека — это то, что вы никогда не захотите делать в интерпретаторе, это значительно замедляет выполнение кода, джиттер должен делать это только один раз.

person Hans Passant    schedule 27.07.2016

Из Общие Языковая инфраструктура (CLI), раздел I: концепции и архитектура, раздел 12.1:

... CLI поддерживает только подмножество этих типов в своих операциях над значениями, хранящимися в его оценочном стеке — int32, int64 и native int. Кроме того, интерфейс командной строки поддерживает внутренний тип данных для представления значений с плавающей запятой во внутреннем стеке вычислений.

...

Как описано ниже, в инструкциях CIL не указываются типы операндов. Вместо этого CLI отслеживает типы операндов на основе потока данных и с помощью требования согласованности стека, описанного ниже. Например, одна инструкция add добавит из стека два целых числа или два числа с плавающей запятой.

"Ниже" обсуждение согласованности стека относится к разделу 12.3.2.1:

Стек оценки состоит из слотов, которые могут содержать данные любого типа, включая неупакованный экземпляр типа значения. Состояние типа стека (глубина стека и типы каждого элемента в стеке) в любой заданной точке программы должно быть одинаковым для всех возможных путей потока управления. Например, программа, которая зацикливается неизвестное количество раз и помещает новый элемент в стек на каждой итерации, будет запрещена.

То есть всякий раз, когда он сталкивается с инструкцией add, он всегда знает «форму» стека в этой точке и поэтому может построить правильные собственные инструкции. И в любом случае он работает с ограниченным набором типов.

(Другие характеристики интерфейса командной строки можно найти на этой странице)

person Damien_The_Unbeliever    schedule 27.07.2016

Если вы напишете тестовую программу на C# и декомпилируете ее в MSIL, вы увидите, что размер задается инструкциями ldc или conv перед вызовом add.

person Lex Li    schedule 27.07.2016