Подтвердить что ты не робот

Что такое MethodImplOptions.InternalCall?

Многие методы в BCL отмечены атрибутом [MethodImpl(MethodImplOptions.InternalCall)]. Этот указывает, что "метод реализован в самой общей среде выполнения языка".

Какова была необходимость в разработке структуры таким образом, чтобы указать конкретные инструкции CIL, которые будут принудительно внедрены во время выполнения? В конечном счете, атрибут создает контрактные обязательства для среды выполнения, но таким образом, который кажется мне запутанным и не сразу очевидным.

Например, Math.Pow мог быть написан таким образом (извините мою неформальную смесь С# + IL и самого IL, если это плохо, это всего лишь образец, чтобы объяснить мою точку зрения):

public static double Pow(double x, double y)
{
    ldarg.0
    ldarg.1
    pow // Dedicated CIL instruction
    ret
}

вместо текущего способа:

[MethodImpl(MethodImplOptions.InternalCall)]
public static double Pow(double x, double y);

Почему существует MethodImplOptions.InternalCall?

4b9b3361

Ответ 1

Я думаю, что большая причина в том, что создать новую инструкцию IL довольно сложно, и это может повлиять на множество инструментов, включая внешние (ILGenerator, ilasm, ildasm, PEVerify, Reflector, PostSharp,...).

Но создаем новый метод InternalCall? Это почти так же просто, как написать метод в С# (я полагаю, я не смотрел на Rotor для проверки), и это ничего не влияет.

И это не только о его создании, я думаю, что то же самое относится и к обслуживанию.

Ответ 2

Я думаю, что это не слишком усложняло CLR. Когда я впервые посмотрел на CIL, я не мог не заметить сходства с языком ассемблера и, более того, ограниченные инструкции, почти как если бы они заставили его работать непосредственно на процессоре.

В теории, когда CLR JIT, что образец кода для Pow, который вы включили в свой пост, ему придется выдать собственный код для инструкции Pow, так как нет никакой нативной инструкции (или это? haven с тех пор прошло несколько лет). С точки зрения производительности, но и с точки зрения реализации, гораздо проще просто вызвать mscorlib для кода Pow, чем просто "вставить" его в строку.

Или у них могла быть таблица поиска для общих функций mscorlib, которые являются InternalCall и заменяют инструкцию вызовом самой функции. Но опять же, не все InternalCall так просты.

Я думаю, что это был компромисс для удобства; как на их стороне, так и для удобства обслуживания CLR, более унифицированного стандарта CLI и обеспечения некоторой гибкости для абонентов.

Нижняя строка - это то, что я еще не разработал CLR, и это совсем не в моей голове. Что-то я бы сделал, я думаю.

Ответ 3

Метод является родным, TRULY native, реализованным в самой Runtime. Не забывайте, что CLR происходит от С++. Это как в компиляторе. В реальном мире CIL действительно не выполняется. Он JIT-ted, а затем выполняется, как компилятор, с помощью среды выполнения C/С++. Math.Pow - это, скорее всего, [умозрение] вызов в собственном методе C/С++ math.h pow и его реализация - теперь NET и Mono реализуют CLR.

В UnityEngine.dll [MethodImpl(MethodImplOptions.InternalCall)] используется для большинства собственных внешних методов. Однако эти С++-методы используют библиотеку CLR Mono С++, и они могут взаимодействовать с С# более интимным способом, чем сам P/INVOKE. И еще более эффективный (PInvoke скрывает некоторые детали реализации и затрудняет понимание)

Однако единственный способ использовать [MethodImpl(MethodImplOptions.InternalCall)] - это то, что вы являетесь самой средой CLR - я только тестировал Mono, как это. Я не знаю, возможно ли даже изменить реализацию Microsoft CLR, но с Mono вы можете злоупотреблять этой функцией.

Кроме того, не путайте это с [MethodImpl(MethodImplOptions.Unmanaged)] - это совершенно другая история.

Подробнее о внутренних вызовах и способах работы Mono: http://www.mono-project.com/docs/advanced/embedding/

Отказ от ответственности: Я НЕ отношусь к Unity или Mono!