2016-12-06 3 views
4

В Интернете есть много статей, в которых перечислены оптимизации, сделанные C# JIT, перед выполнением части кода. Например this post на MSDN говорит о:Содержит ли C# JIT-компилятор нулевую проверку?

Constant складывании, постоянное и копии распространения Общих подвыражения выбывания движения Код инвариантов цикла, Мертвого магазина и мертвого код исключения, распределение регистров, методы встраивания, Loop разворачивая (небольшие петли с малыми телами).

Мой вопрос: компилятор JIT имеет дело с бесполезными нуль-чеками? Я не могу найти источник, рассматривающий этот вопрос.

В той же статье я прочитал:

поскольку спецификация C# языка гарантирует, что любой вызов на ссылке на объект нулевой бросает NullReferenceException, каждый вызов сайт должны обеспечить экземпляр не является нулевым. Это делается путем разыменования справки экземпляра ; если он равен нулю, он будет генерировать ошибку, которая равна , превратившемуся в это исключение.

Итак, предположим, что я пишу кусок кода, как это:

if (person != null) 
{ 
    Console.WriteLine(person.Name); 
} 

В person.Name звонки снова второй нуль-проверить, что это Клири бесполезно, и компилятор может удалить его. Или нет?

Я прочитал, что на Java это уже сделано (некоторые источники между многими here, here и here).

Если C# тоже это делает, знаете ли вы какой-то источник или документацию, которые об этом говорят?

Если вместо этого C# не делает этого, вы знаете, почему? Есть ли внутренняя трудность в реализации такой функции для среды .NET, с которой JIT Java не сталкивается?

+2

Только как побочный эффект обычной оптимизации, такой как устранение мертвого кода. Это должно быть довольно редко.В целом оптимизатор дрожания не имеет специального знания о коде, выполняющем проверку нулевого указателя, и рассматривает указатели как изменчивые. Довольно важно в любой VM с сборщиком мусора, который произвольно изменяет указатели, когда он уплотняет кучу. Примечательно, что сам компилятор C# может исключить проверку, он делает это, когда вы используете оператор elvis ('? .'). –

ответ

3

Null проверка оптимизации, выполняемая компилятором (Roslyn, not Jitter) in several cases, когда его полностью сохранить, чтобы сделать это.

Например, если вы используете ? (оператор Элвиса).

IL_0006: stloc.0    // Pop a value from stack into local variable 0 
IL_0007: ldloc.0    // Load local variable 0 onto stack 
IL_0008: brtrue.s IL_000c  // Branch to target if value is non-zero (true), short form 
IL_000a: br.s IL_0013   // Branch to target, short form 
IL_000c: ldloc.0    // Load local variable 0 onto stack 
IL_000d: call instance void Foo::Bar() // Call method indicated on the stack with arguments 

Другой пример такой код:

new Bar().Foo(); 

компилятор генерирует для этой call инструкции и не callvirt (что означает, без проверки нуля на this)

В других случаях не могу быть уверен, что this не будет пустым.

В любом случае, нулевой чек действительно очень быстро.

Смежные вопросы