Jitter logic to remove unbox_any

I am studying the execution of this C # code:

public static void Test<T>(object o) where T : class { T t = o as T; } 

Equivalent IL code:

 .method public static void Test<class T>(object A_0) cil managed { // Code size 13 (0xd) .maxstack 1 .locals init (!!T V_0) IL_0000: ldarg.0 IL_0001: isinst !!T IL_0006: unbox.any !!T IL_000b: stloc.0 IL_000c: ret } // end of method DemoType::Test 

Based on this answer ( unnecessary unbox_any ), can anyone explain to me what the exact logic that Jitter does here is; how exactly the jitter decided to ignore the "unbox_any" instruction in this particular case (theoretically, according to MSDN, a NullReferenceException should be thrown when the isinst instruction gives null, but this does not happen in practice!)

Update

Based on usr's answer and Hans's comment, if obj is a reference type, castclass will be called and therefore no NRE.

But what about the following case?

 static void Test<T>(object o) where T : new() { var nullable = o as int?; if (nullable != null) //do something } Test<int?>(null); 

And the equivalent IL code (partial):

 IL_0001: ldarg.0 IL_0002: isinst valuetype [mscorlib]System.Nullable`1<int32> IL_0007: unbox.any valuetype [mscorlib]System.Nullable`1<int32> IL_000c: stloc.0 IL_000d: ldloca.s nullable IL_000f: call instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue() IL_0014: stloc.1 IL_0015: ldloc.1 IL_0016: brfalse.s IL_0024 

In this case, its type value is so why NRE is not thrown?

+4
source share
2 answers

When applied to a reference type, the unbox.any command has the same effect as the castclassTok type.

T limited to a reference type. In this case, this instruction does not throw an NRE. JIT does not β€œignore” it; it executes it as indicated. JIT has no right to ignore instructions.

The documentation has an instruction

A NullReferenceException is thrown if obj is a null reference.

which is misleading because it applies only to value types. The first statement that I quoted is unequivocal.

+1
source

In order to answer the second case (question updating section) of the NULL value type, we need to carefully study the CLI ECMA specification (III.4.33 unbox.any - convert the type to value in the box):

A System.NullReferenceException is thrown if obj is null and typeTok is a value type with a null value

The resulting translucent portion is missing from the MSDN documentation.

So, to summarize the behavior of unbox_any:

  • If typeTok is type ref, the same behavior as castclass
  • If typeTok is the value type:

    2.1. If obj is null and typeTok is a null value type, the result is null

    2.2. If obj is null and Tok is not a NULL type, a NullReferenceException will be thrown

If I understand correctly, the behavior of paragraph 2.2 is the same as the usual unbox operation, see jitter source code

+1
source

Source: https://habr.com/ru/post/1238418/


All Articles