2015-07-22 23 views
35

Dopo l'aggiornamento a .net 4.6 abbiamo scoperto un bug in cui RyuJit produce risultati errati, per il momento siamo stati in grado di aggirare il problema aggiungendo useLegacyJit enabled = "true" a app.config.RyuJit produce risultati errati

Come è possibile eseguire il debug del codice macchina generato da quanto segue?

Ho creato un nuovo progetto di console in VS 2015 RTM, impostato su Rilascio, Qualsiasi CPU, deselezionato Prefer 32 bit, in esecuzione con e senza debugger collegato produce lo stesso risultato.

using System; 
using System.Runtime.CompilerServices; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine(Calculate()); 
      Console.WriteLine(Calculate()); 

      Console.ReadLine(); 
     } 

     [MethodImpl(MethodImplOptions.AggressiveInlining)] 
     public static Value Calculate() 
     { 
      bool? _0 = (bool?)null; 
      bool? _1 = (bool?)true; 
      if (!Value.IsPresent<bool>(_1)) 
      { 
       return default(Value); 
      } 

      bool? result = null; 
      result = (_1.Value ? new bool?(false) : result); 
      if (_0.HasValue && _0.Value) 
      { 
      } 
      return new Value(result); 
     } 

     public struct Value 
     { 
      bool? _value; 

      public Value(bool? value) 
      { 
       _value = value; 
      } 

      public static bool IsPresent<T>(bool? _) 
      { 
       return _.HasValue; 
      } 

      public override string ToString() 
      { 
       return _value.ToString(); 
      } 
     } 
    } 
} 

Dovrebbe produrre: False Falso

ma invece produce: Vero Falso

La parte fondamentale dell'esempio è

result = true ? false : result; 

che dovrebbe sempre ritorno falso, ma come puoi vedere dall'output, restituisce True la prima volta t Il metodo viene eseguito e una risposta diversa la seconda volta che viene eseguito il metodo. Rimuovendo alcune righe dal metodo Calculate(), verrà restituito True sempre, ma l'esempio dato è il più vicino che potrei riprodurre nel nostro scenario di produzione reale.

+5

Sì, si tratta di un bug di ottimizzazione inlining. Il primo Calculate inline() ha una cattiva istruzione. Mi sembra che ci sia un '!' Da qualche parte all'interno dell'ottimizzatore che non dovrebbe essere lì. Nulla di ciò che possiamo fare per correggere questo bug, è possibile segnalarlo su connect.microsoft.com. Basta licenziare MethodImplOptions.AggressiveInlining per un po ', è improbabile che sia stato ampiamente testato. –

+0

Il codice di produzione effettivo non ha l'attributo AggressiveInlining, ma questo è l'unico modo in cui è possibile riprodurre il comportamento in questo piccolo esempio. Il codice di produzione è stato parzialmente generato dalla macchina, motivo per cui il codice di esempio sembra un po 'strano. L'ho appena segnalato su https://connect.microsoft.com/VisualStudio/feedback/details/1578173 – BrandonAGr

+0

@BrandonAGr Questo bug è causato durante l'inlining? Usare 'MethodImplOptions.NoInlining' è un possibile aggiramento? – Andre

risposta

27

Grazie per il programma di riproduzione isolato e posso confermare che si tratta effettivamente di un bug RyuJIT nell'ottimizzatore che è stato esposto a causa dell'inlinazione. Ho fatto una correzione al compilatore e ho trovato i dettagli del roll out. Non trasformare SO in un bug tracker e per una soluzione più rapida: [email protected]

+3

Ho creato una versione semplificata del codice sorgente, la puoi trovare nel repository coreclr: https : //github.com/dotnet/coreclr/issues/1299 – AndreyAkinshin

+1

@HansPassant Sì, non si trattava di una segnalazione di bug, il tipo di domanda nascosta era come trovare il codice macchina in esecuzione. L'esempio semplificato di Andrey ha reso molto semplice la visualizzazione del disassemblaggio in Visual Studio, ovviamente non è ancora facile capire quali registri reggono cosa, ma sono stato in grado di attraversarlo. – BrandonAGr

+0

@schellap Questa correzione risolve anche - https : //connect.microsoft.com/VisualStudio/Feedback/Details/1602437? –

Problemi correlati