"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com...
| Willy Denoyette [MVP] <wi************ *@telenet.be> wrote:
| > The only way to debug at that level without interfering with the JIT
(which
| > will turn of inlining whenever a managed debugger is attached) is by
using
| > an unmanaged debugger like cdb or windbg. These debuggers are freely
| > downloadable from
| >
http://www.microsoft.com/whdc/devtoo...nstallx86.mspx
|
| cordbg allows you to keep JIT optimizations, including inlining - type
| m JitOptimization s 1
| to set this.
|
| For example, here's some sample C# code:
| using System;
|
| class Program
| {
| static void Main()
| {
| for (int i=0; i < 10; i++)
| {
| Console.WriteLi ne (Square(i));
| }
| }
|
| static int Square (int x)
| {
| return x*x;
| }
| }
|
|
| Here's the disassembly of Main with optimization off:
| [0000] push ebp
| [0001] mov ebp,esp
| [0003] push eax
| [0004] push edi
| [0005] push esi
| [0006] xor esi,esi
| *[0008] xor esi,esi
| [000a] nop
| [000b] jmp 00000015
| [000d] mov ecx,esi
| [000f] call dword ptr ds:[00A150E4h]
| [0015] mov edi,eax
| [0017] mov ecx,edi
| [0019] call dword ptr ds:[79C56664h]
| [001f] inc esi
| [0020] cmp esi,0Ah
| [0023] jl FFFFFFEA
| [0025] nop
| [0026] pop esi
| [0027] pop edi
| [0028] mov esp,ebp
| [002a] pop ebp
| [002b] ret
|
|
| And here it is with optimization on:
|
| (cordbg) dis 20
| [0000] push esi
| *[0001] xor esi,esi
| [0003] mov eax,esi
| [0005] imul eax,esi
| [0008] mov edx,eax
| [000a] mov ecx,dword ptr ds:[01C42030h]
| [0010] mov eax,dword ptr [ecx]
| [0012] call dword ptr [eax+000000BCh]
| [0018] inc esi
| [0019] cmp esi,0Ah
| [001c] jl FFFFFFE7
| [001e] pop esi
| [001f] ret
|
| Note the inlining of the multiplication in the second version.
|
You are right that the call to Square is inlined, but that's normal, the CLR
tests the "IsDebugger " atached flag at the first hit of a (managed)
breakpoint in your code, that is after Main is JIT compiled, so, after the
inlining has been done (in optimized build).
subsequent JIT compiles are not guaranteed to be optimized, unless you have
set the "JitOptimizatio ns" mode flag, but the result is not pretty, it's
quite hard to debug with this flag set and the disassembly output cannot be
trusted.
Here is the VS debugger output, which includes the actual address and code
bytes, note that you ran this on V1.1, so I've included the V2. code here
[1] so you can watch the differences between v1 and V2, which may be quite
interesting.
02D1005F 33 F6 xor esi,esi
02D10061 8B D6 mov edx,esi
02D10063 0F AF D6 imul edx,esi
02D10066 8B 0D 30 20 B4 01 mov ecx,dword ptr ds:[1B42030h]
02D1006C 8B 01 mov eax,dword ptr [ecx]
02D1006E FF 90 BC 00 00 00 call dword ptr [eax+0BCh]
02D10074 46 inc esi
02D10075 83 FE 0A cmp esi,0Ah
02D10078 7C E7 jl 02D10061
02D1007A 5E pop esi
02D1007B C3 ret
Here is the same but running under V2.
00CB0077 33 F6 xor esi,esi
00CB0079 EB 2D jmp 00CB00A8
00CB007B 8B C6 mov eax,esi
00CB007D 0F AF C6 imul eax,esi
00CB0080 8B F8 mov edi,eax
00CB0082 83 3D 84 10 27 02 00 cmp dword ptr ds:[2271084h],0
00CB0089 75 0A jne 00CB0095
00CB008B B9 01 00 00 00 mov ecx,1
00CB0090 E8 77 D7 69 78 call 7934D80C
00CB0095 8B 0D 84 10 27 02 mov ecx,dword ptr ds:[2271084h]
00CB009B 8B D7 mov edx,edi
00CB009D 8B 01 mov eax,dword ptr [ecx]
00CB009F FF 90 BC 00 00 00 call dword ptr [eax+0BCh]
00CB00A5 83 C6 01 add esi,1
00CB00A8 83 FE 0A cmp esi,0Ah
00CB00AB 0F 9C C0 setl al
00CB00AE 0F B6 C0 movzx eax,al
00CB00B1 85 C0 test eax,eax
00CB00B3 75 C6 jne 00CB007B
00CB00B5 5E pop esi
00CB00B6 5F pop edi
00CB00B7 C3 ret
Noticed the main differences?
Willy.