NOP는

2009-10-23 1 views
6

내가 VS2010 베타 2에서 F 번호와 함께 연주하고, 나는 F 번호에 새로운 오전부터, 난 그냥 일반적인 예 중 하나를 포착하고 나서서으로 계승 기능을 구현 :NOP는

let rec factorial n = 
    if n <= 1 then 1 else n * factorial (n - 1);; 
나는 F # 코드의 리플렉터의 C#을 표현을 컴파일하는 경우

public static int Factorial(int n) { 
    if (n <= 1) 
     return 1; 

     return n * Factorial(n - 1); 
} 

그래서, 나는 동일한 IL를 얻을 기대 :

나는이를 구축하고 반사경에서 생성 된 코드를 보면, 나는 해당하는 C# 코드를 얻을.

그러나 릴리스 모드에서 이러한 스 니펫을 모두 컴파일하고 생성 된 IL을 비교하면 기능적으로 동일하지만 여전히 약간 다릅니다.

.method public static int32 factorial(int32 n) cil managed 
{ 
    .maxstack 5  <=== Different maxstack 
    L_0000: nop  <=== nop instruction? 
    L_0001: ldarg.0 
    L_0002: ldc.i4.1 
    L_0003: bgt.s L_0007 
    L_0005: ldc.i4.1 
    L_0006: ret 
    L_0007: ldarg.0 
    L_0008: ldarg.0 
    L_0009: ldc.i4.1 
    L_000a: sub 
    L_000b: call int32 FSharpModule::factorial(int32) 
    L_0010: mul 
    L_0011: ret 
} 

생성 된 코드가 상이한 MAXSTACK 및 F # 1에있어서의 추가적인 NOP 명령을 제외하고 동일하다 :

.method public hidebysig static int32 Factorial(int32 n) cil managed 
{ 
    .maxstack 8 
    L_0000: ldarg.0 
    L_0001: ldc.i4.1 
    L_0002: bgt.s L_0006 
    L_0004: ldc.i4.1 
    L_0005: ret 
    L_0006: ldarg.0 
    L_0007: ldarg.0 
    L_0008: ldc.i4.1 
    L_0009: sub 
    L_000a: call int32 TestApp.Program::Factorial(int32) 
    L_000f: mul 
    L_0010: ret 
} 

은 F # 구현로 컴파일 님

는 C# 구현 컴파일한다.

이것은 아마도 중요하지 않지만 F # 컴파일러가 릴리스 빌드에 NOP를 삽입하는 이유에 대해 궁금합니다.

이유를 설명 할 수 있습니까?

(필자는 F # 컴파일러가 C# 컴파일러와 동일한 수준의 실제 테스트를 수행하지 못했지만이 과정이 너무 명확하기 때문에 잡혔을 것이라고 생각합니다.)

편집 (참조 어셈블리 간결 제거)

C:\Program Files\Microsoft F#\v4.0\fsc.exe -o:obj\Release\FSharpLib.dll 
--debug:pdbonly --noframework --define:TRACE --optimize+ 
--target:library --warn:3 --warnaserror:76 --vserrors --utf8output --fullpaths 
--flaterrors "C:\Temp\.NETFramework,Version=v4.0.AssemblyAttributes.fs" Module1.fs 

를 다음과 같이 컴파일 명령이다.

답변

17

maxstack의 차이점은 C# 컴파일러가 코드가 작을 때마다 사용되는 "light"메서드 본문 머리글을 사용하여 첫 번째 메서드를 컴파일하므로 예외가없고 지역도 없습니다. 이 경우 maxstack은 지정되지 않고 기본값은 8입니다.

F # 컴파일러는«fat»메서드 본문 헤더를 사용하고 계산 된 maxstack을 지정합니다.

nop의 경우 디버그 모드에서 컴파일 중이기 때문입니다. 그들은 항상 nop으로 메소드 본문을 시작합니다. fsharp/ilxgen.ml에서 참조 :

// Add a nop to make way for the first sequence point. There is always such a 
// sequence point even when zapFirstSeqPointToStart=false 
do if mgbuf.cenv.generateDebugSymbols then codebuf.Add(i_nop); 

을 내가 디버그 기호없이 계승을 컴파일하면, 내가 NOP를하지 않습니다.

+0

음, VS2010의 기본 "릴리스"빌드 프로파일을 사용하므로 실제로 릴리스 모드로 구축 중이라고 가정합니다. 출력 창에 "Build started : Project : FSharpLib, Configuration : 모든 CPU 해제"라고 표시됩니다. "debug"로 변경하면 완전히 다른 MSIL이 예상대로 발생합니다. –

+0

F # 1.9.7.8과 명령 줄을 사용하여 테스트하고 있습니다. 만약 내가/디버깅을 통과하지 못하면 안돼. –

+0

컴파일에 대한 명령 줄로 질문을 업데이트했으며 fsc.exe를 사용하여 직접 컴파일하려고했습니다. 같은 결과. 출력 창에 따르면 VS2010b2는 버전 번호가 1.9.7.4 인 F # 버전을보고 할 때 최신 컴파일러와 함께 제공되지 않습니다. 그 차이가있을 수 있을까요? –