How can we help you today? How can we help you today?

Reflector doesn't understand type casting

I found that reflector has a problem in situations where type casting is happened.
One small example is the List<T> class of .NET Framework.

Let's look at the original Microsoft code:
// Sets or Gets the element at the given index.
        //
        public T this&#91;int index&#93; &#123;
            get &#123; 
                // Fllowing trick can reduce the range check by one
                if &#40;&#40;uint&#41; index &gt;= &#40;uint&#41;_size&#41; &#123; 
                    ThrowHelper.ThrowArgumentOutOfRangeException&#40;&#41;; 
                &#125;
                return _items&#91;index&#93;; 
            &#125;
            set &#123;
                if &#40;&#40;uint&#41; index &gt;= &#40;uint&#41;_size&#41; &#123;
                    ThrowHelper.ThrowArgumentOutOfRangeException&#40;&#41;; 
                &#125;
                _items&#91;index&#93; = value; 
                _version++; 
            &#125;
        &#125;
And please compare with Reflector result:
public T this&#91;int index&#93;
&#123;
    get
    &#123;
        if &#40;index &gt;= this._size&#41;
        &#123;
            ThrowHelper.ThrowArgumentOutOfRangeException&#40;&#41;;
        &#125;
        return this._items&#91;index&#93;;
    &#125;
    set
    &#123;
        if &#40;index &gt;= this._size&#41;
        &#123;
            ThrowHelper.ThrowArgumentOutOfRangeException&#40;&#41;;
        &#125;
        this._items&#91;index&#93; = value;
        this._version++;
    &#125;
&#125;
Reflector skips type casting at the line:
if ((uint) index >= (uint)_size) {
That makes disassembled code erratic.

If we look at IL code, all is correct:
.method public hidebysig specialname newslot virtual final instance !T get_Item&#40;int32 index&#41; cil managed
&#123;
    .maxstack 8
    L_0000: ldarg.1 
    L_0001: ldarg.0 
    L_0002: ldfld int32 System.Collections.Generic.List`1&lt;!T&gt;::_size
    L_0007: blt.un.s L_000e
    L_0009: call void System.ThrowHelper::ThrowArgumentOutOfRangeException&#40;&#41;
    L_000e: ldarg.0 
    L_000f: ldfld !0&#91;&#93; System.Collections.Generic.List`1&lt;!T&gt;::_items
    L_0014: ldarg.1 
    L_0015: ldelem.any !T
    L_001a: ret 
&#125;
Reflector doesn't translate blt.un.s instruction properly.
Sergey Korostel
0

Comments

3 comments

  • James Moore
    Hi Sergey,

    Thanks for the bug report. I have poped this in our bug tracking system (Ref RR-19) and we will take a look at it over the next month or so and see if we can get the code generation working more accurately in this case.

    Regards,

    James
    James Moore
    0
  • DxCK
    this bug is still there...
    DxCK
    0
  • random832
    .method public hidebysig specialname newslot virtual final instance !T get_Item&#40;int32 index&#41; cil managed
    &#123;
        .maxstack 8
        L_0000: ldarg.1 
        L_0001: ldarg.0 
        L_0002: ldfld int32 System.Collections.Generic.List`1&lt;!T&gt;::_size
        L_0007: blt.un.s L_000e
        L_0009: call void System.ThrowHelper::ThrowArgumentOutOfRangeException&#40;&#41;
        L_000e: ldarg.0 
        L_000f: ldfld !0&#91;&#93; System.Collections.Generic.List`1&lt;!T&gt;::_items
        L_0014: ldarg.1 
        L_0015: ldelem.any !T
        L_001a: ret 
    &#125;
    
    It's not exactly 'type casting' that it doesn't support (there is casting in the C# code, and that's how you would represent this code, but there's no conv instruction), but rather the use of unsigned comparisons on what was a signed variable. It should probably be surrounded in unchecked() too [I'm guessing that the MS source code in question was compiled in uncheckd mode... though really reflector should detect when checked vs unchecked are used when it's significant]

    For this code the trick is just that, a trick - neither value is expected to ever _actually_ be negative, it's just that the unsigned branch instruction is less expensive (by "one" apparently. one what, we may never know). But in the general case this would be a good thing to fix.
    random832
    0

Add comment

Please sign in to leave a comment.