2009-10-23 10 views
6

sto giocando con F # in VS2010 beta2, e dato che io sono nuovo di F #, ho appena preso uno degli esempi più comuni ed è andato avanti e ha implementato una funzione fattoriale come:NOP in build di rilascio di codice F #

let rec factorial n = 
    if n <= 1 then 1 else n * factorial (n - 1);; 

Se costruisco questo e guardare il codice generato in Reflector, ottengo il codice C# corrispondente:

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

     return n * Factorial(n - 1); 
} 

Quindi, se compilo rappresentazione C# del riflettore del codice F #, mi sarei aspettato di ottenere identici iL.

Tuttavia, se compilo entrambi questi frammenti nella modalità di rilascio e confrontare l'IL generato, sono diversi (sono funzionalmente identici, ma differisce ancora un po ').

Il C# attuazione compila a:

.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 
} 

La # attuazione F compila a:

.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 
} 

Il codice generato è identico salvo diversa maxstack e l'istruzione NOP supplementare nel metodo F #.

Questo probabilmente non è significativo, ma sono curioso di sapere perché il compilatore F # sarebbe inserire NOP in una build di rilascio.

Qualcuno può spiegare perché?

(Sono perfettamente consapevole che il compilatore F # non ha superato lo stesso livello di test del mondo reale del compilatore C#, ma è così ovvio che l'immagine sarebbe stata catturata).

EDIT: Il comando di compilazione è il seguente

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 

(assembly referenziati rimosse per brevità).

risposta

17

differenza Il maxstack è dovuto al fatto che il C# compilatore compila il primo metodo con una «luce» intestazione corpo del metodo, che viene utilizzato quando il codice è piccolo, non ha eccezioni e nessuna locali. In tal caso, il maxstack non viene specificato e il valore predefinito è 8.

Il compilatore F # utilizza un'intestazione del corpo del metodo «grasso» e specifica il valore massimo che ha calcolato.

Per quanto riguarda il PON, è perché si sta compilando in modalità debug. Iniziano sempre un metodo body con un nop. Vedere da 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); 

Se compilo il tuo fattoriale, senza simboli di debug, non ottengo un NOP.

+0

Beh, io uso il "rilascio" di default costruire profilo in VS2010, quindi presumo che sto costruendo in realtà nella modalità di rilascio. La finestra di output dice "Build started: Project: FSharpLib, Configuration: Release Any CPU". Se cambio in "debug" ottengo MSIL completamente diverso come previsto. –

+0

Sto testando con F # 1.9.7.8 e la riga di comando. Se non passo/debug, non ottengo un nop. –

+0

Ho aggiornato la domanda con la riga di comando per la compilazione e ho provato a compilare utilizzando fsc.exe direttamente. Stesso risultato Secondo la finestra di output VS2010b2 non viene fornito con il compilatore più recente in quanto riporta un numero di versione di F # versione 1.9.7.4. Potrebbe essere la differenza? –