Будет ли .NET JIT встроить небольшую функцию, которая вызывает другую маленькую функцию? - PullRequest
6 голосов
/ 31 июля 2010

Хотелось бы знать - будут ли .NET JITter рекурсивно встроенными маленькими функциями вызываться из других маленьких функций?

Просто например:

public static float Square(float value)
{
    return value * value;
}

public static float Cube(float value)
{
    return Square(value) * value;
}

Если я вызову Cube откуда-нибудь, он будет встроен полностью или я в итоге вызову функции Square?

И, если да, то насколько глубоко он вернется к выполнению встраивания? (Скажем, я был достаточно сумасшедшим, чтобы реализовать функцию Quartic или Quintic таким же образом.)

1 Ответ

10 голосов
/ 31 июля 2010

К сожалению, вы выбрали плохой пример.JIT-компилятор x86 не содержит встроенных методов, возвращающих float.Не уверен на 100%, почему, я думаю, это помогает избежать постоянных проблем, когда число с плавающей запятой преобразуется в 80-битное значение с плавающей запятой в FPU.Внутренняя точность составляет 80 бит, но эти дополнительные биты обрезаются, когда 80-битное значение усекается до 32-битного значения, когда оно сбрасывается обратно в память.Слишком длительное сохранение значения в FPU предотвращает возникновение этого усечения и приводит к изменению результата вычисления.

Если вы замените float на double и скомпилируете этот код:

static void Main(string[] args) {
    Console.WriteLine(Cube(2.0));
}

Тогда этот машинный кодгенерируется при включенном оптимизаторе JIT:

00000000  push        ebp                             ; setup stack frame
00000001  mov         ebp,esp 
00000003  call        6DA2BEF0                        ; Console.get_Out() 
00000008  fld         qword ptr ds:[010914B0h]        ; ST0 = 8.0
0000000e  sub         esp,8                           ; setup argument for WriteLine
00000011  fstp        qword ptr [esp] 
00000014  mov         ecx,eax                         ; call Console.Out.WriteLine
00000016  mov         eax,dword ptr [ecx] 
00000018  call        dword ptr [eax+000000D0h] 
0000001e  pop         ebp                             ; done
0000001f  ret

Он не только встроил функции, но и мог вычислять выражения во время компиляции.И напрямую передает результат, вызывая Console.WriteLine (8.0).Довольно хорошо, да?

Используй double, а не float.

...