Хочу на досуге поковыряться в кишках компилятора, а точнее в той ее части, что отвечает за кодогенерацию с целью улучшения качества выхлопа...
Например, можно начать с циклов. Сейчас вот для такого простейшего цикла
private Test(args: array[string]) : void
{
unchecked
{
foreach (i in args)
WriteLine(i);
}
}
генерируется такой IL, на который не рассчитывает джит, в результате проверки за выход границы массива не устраняются. Не говоря уже о мелочах, таких как 2 инициалиазации переменной счетчика и использование более длинной инструкции
callvirt instance int32 [mscorlib]System.Array::get_Length(), а не
ldlen, что увеличивает размер метода. Для примера тот же самый код, сгенерированный C# имеет размер 25 байт против 38 у Nemerle.
| MSIL |
| // Code size 38 (0x26)
.maxstack 2
.locals init (
[0] int32,
[1] string
)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldc.i4.0 // зачем-то
IL_0003: stloc.0
// loop start (head: IL_0004)
IL_0004: ldloc.0
IL_0005: ldarg.0
IL_0006: callvirt instance int32 [mscorlib]System.Array::get_Length()
IL_000b: clt
IL_000d: brfalse IL_0025
IL_0012: ldarg.0
IL_0013: ldloc.0
IL_0014: ldelem.ref
IL_0015: stloc.1
IL_0016: ldloc.1
IL_0017: call void [mscorlib]System.Console::WriteLine(string)
IL_001c: ldloc.0
IL_001d: ldc.i4.1
IL_001e: add
IL_001f: stloc.0
IL_0020: br IL_0004
// end loop
IL_0025: ret
|
| |
Для сравнения выхлоп джита для C#:
| ASM (C#) |
| 00007FFBEBEE0494 xor edi,edi
00007FFBEBEE0496 mov ebx,dword ptr [rsi+8]
00007FFBEBEE0499 test ebx,ebx
00007FFBEBEE049B jle 00007FFBEBEE04B0
start:
00007FFBEBEE049D movsxd rcx,edi
00007FFBEBEE04A0 mov rcx,qword ptr [rsi+rcx*8+10h]
00007FFBEBEE04A5 call 00007FFC40CDDE80
00007FFBEBEE04AA inc edi
00007FFBEBEE04AC cmp ebx,edi
00007FFBEBEE04AE jg start
00007FFBEBEE04B0 add rsp,20h
...
00007FFBEBEE04B7 ret
|
| |
и Nemerle
| ASM (Nemerle) |
| 00007FFBEBEC0493 xor edi,edi
start:
00007FFBEBEC0495 mov rcx,rsi
00007FFBEBEC0498 cmp dword ptr [rcx],ecx
00007FFBEBEC049A call 00007FFC4B4CCB40
00007FFBEBEC049F cmp eax,edi
00007FFBEBEC04A1 jle 00007FFBEBEC04BB
00007FFBEBEC04A3 mov ecx,dword ptr [rsi+8]
00007FFBEBEC04A6 cmp edi,ecx
00007FFBEBEC04A8 jae 00007FFBEBEC04C2
00007FFBEBEC04AA movsxd rcx,edi
00007FFBEBEC04AD mov rcx,qword ptr [rsi+rcx*8+10h]
00007FFBEBEC04B2 call 00007FFC40CDDE80
00007FFBEBEC04B7 inc edi
00007FFBEBEC04B9 jmp start
00007FFBEBEC04BB add rsp,28h
...
00007FFBEBEC04C1 ret
00007FFBEBEC04C2 call 00007FFC4B967BE0
00007FFBEBEC04C7 int 3
|
| |
В общем, код надо реорганизовать таким образом:
int i = 0;
goto start;
again:
Console.WriteLine(args[i]);
i = i + 1;
start:
if (i < args.Length)
goto again;
Теперь вопрос. Где копать и куда смотреть?
И главное. Я не могу открыть проект компилятора в студии. На все проекты пишет Load failed.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>