Possible problem in x64 JIT when tail calling - by Clive Tong

Status : 

  Fixed<br /><br />
		This item has been fixed in the current or upcoming version of this product.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.

Sign in
to vote
ID 1372514 Comments
Status Closed Workarounds
Type Bug Repros 0
Opened 5/27/2015 1:46:03 AM
Access Restriction Public


Our product is a profiler that uses third party product for pdf rendering of a call graph.
On upgrading to .NET 4.6 (via installing 2015) this pdf component fails to render correctly when executed from the command line. After some experimentation it appears to work ok when running x86 or when running under the debugger.  Setting the config to use legacy jit gets rid of the issue, so it appears to be a problem in the x64 jit when it is optimizing.

On investigation, a POINTF structure is not being passed correctly when the x64 jit does a tail call. This structure is interesting as it is usually passed as two 32 bit values packed into a 64bit register.

Looking at the code generated for a method of form

internal void a(string A_0, Font A_1, Brush A_2, PointF A_3, StringAlignment A_4, bool A_5, float[] A_6, float A_7)
          base.TextOut(A_0, A_3, A_4, A_5, kerns, size);

this is generating a tail call of form

000007fe`9a2ee18e 8bb424d0000000  mov     esi,dword ptr [rsp+0D0h]
000007fe`9a2ee195 400fb6ce        movzx   ecx,sil
000007fe`9a2ee199 4c8b8424c0000000 mov     r8,qword ptr [rsp+0C0h]
000007fe`9a2ee1a1 8bb424c8000000  mov     esi,dword ptr [rsp+0C8h]
000007fe`9a2ee1a8 448bce          mov     r9d,esi
000007fe`9a2ee1ab 898c24c0000000  mov     dword ptr [rsp+0C0h],ecx
000007fe`9a2ee1b2 4c89a424c8000000 mov     qword ptr [rsp+0C8h],r12
000007fe`9a2ee1ba f30f104c2438    movss   xmm1,dword ptr [rsp+38h]
0:000> u
000007fe`9a2ee1c0 f30f118c24d0000000 movss dword ptr [rsp+0D0h],xmm1
000007fe`9a2ee1c9 488bcd          mov     rcx,rbp
000007fe`9a2ee1cc 488bd7          mov     rdx,rdi
000007fe`9a2ee1cf 4c8b0424        mov     r8,qword ptr [rsp]
000007fe`9a2ee1d3 48b8c0da2c9afe070000 mov rax,7FE9A2CDAC0h
000007fe`9a2ee1dd 0f28742440      movaps  xmm6,xmmword ptr [rsp+40h]
000007fe`9a2ee1e2 4883c458        add     rsp,58h
000007fe`9a2ee1e6 5b              pop     rbx
0:000> u
000007fe`9a2ee1e7 5d              pop     rbp
000007fe`9a2ee1e8 5e              pop     rsi
000007fe`9a2ee1e9 5f              pop     rdi
000007fe`9a2ee1ea 415c            pop     r12
000007fe`9a2ee1ec 415d            pop     r13
000007fe`9a2ee1ee 415e            pop     r14
000007fe`9a2ee1f0 415f            pop     r15
000007fe`9a2ee1f2 48ffe0          jmp     rax

The POINTF (A_3) is at rsp+c0h and has the correct value. It is passed as a 64 bit register value and is set up correctly at 000007fe`9a2ee199 Unfortunately it gets blasted at 000007fe`9a2ee1cf 

If I breakpoint the instruction at 000007fe`9a2ee1cf , and avoid its execution using
  0:000> r rip=000007fe9a2ee1d3
then I get the correct results, so this setting of r8 is definitely changing the results. [I tested it by setting it the first few times, and then in the rendering of our pdf the first few items are positioned correctly]
Sign in to post a comment.
Posted by Microsoft on 6/5/2015 at 12:18 PM

Thanks for a standalone repro. We have investigated the issue and have a fix for it. Since the issue was reported late in .Net 4.6 product cycle, the fix will be make it to a future release of .Net.

Posted by Clive Tong on 5/29/2015 at 6:26 AM
With the attached example, editing the config file to
     <useLegacyJit enabled="1" />
gets back to printing the (1,2) values that I was expecting.
Posted by Clive Tong on 5/29/2015 at 6:18 AM
Please see the attached C# project.
The problem IL has been chopped down to make the chopped.il file.
I build the chopped.dll using
ilasm /dll chopped.il
and peverified that it had no errors using
peverify chopped.dll

If I run the project inside the debugger, hit return, I get the text
{X=1, Y=2}

If I run from the command line I get the text
C:\Users\clive.tong\Documents\Visual Studio 2013\Projects\ConsoleApplication50\ConsoleApplication50\bin\Debug>ConsoleApplication50.exe
hit return

{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
{X=1.847806E-37, Y=0}
Posted by Microsoft on 5/28/2015 at 5:04 PM

Thanks for reporting this issue. Based on the information given, we couldn't repro the issue. We would need either a standalone repro or IL assembly containing the method along with its managed dependencies to investigate this further.

Posted by Microsoft on 5/27/2015 at 2:03 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If you require immediate assistance with this issue, please contact product support at http://support.microsoft.com/ph/1117.