This is a follow-up post for JIT ETW tracing in .NET Framework 4. These are some of the possible strings that might show up in the FailReason field of the MethodJitTailCallFailed event. These are reasons that come from or are checked for by the VM (as compared to the JIT) and are listed in no particular order:
From x86 JIT, we get this list of failure reasons (again in no particular order):
From the 64-bit JIT, we get this list of failure reasons:
It is worth noting that the 64-bit JIT tries to optimize almost all calls into tail calls. The JIT also implies a certain amount of knowledge, intent and analysis when the "tail." IL prefix is used on a call. A normal call (no prefix) is sort of like telling the JIT to make a call however it deems best. The JIT then does some quick conservative checks to see if a tail call is possible and would be as good as or better than a normal call. On the other hand a call with the "tail." prefix is sort of like telling the JIT to try as hard as possible to make a tail call, because the programmer or the compiler did some big analysis and proved that, despite what the JIT might think, the tail call is safe and will be better than a regular call. Thus the only things the JIT has to check for are known problems (verification, security, and implementation limitations).
The x86 JIT, on the other hand, currently only attempts to do a tail call when the IL explicitly uses the "tail." prefix. Thus the x86 JIT only checks for correctness.
It is my understanding that the C# and VB.NET compilers never emit the "tail." instruction prefix, but the C++ and F# compilers generate it automatically, so the programmer has very little control over this condition. So unless you write in IL, or use some form of IL rewriter, your ability to add or remove the ".tail" prefix is limited at best.
Lastly if you're still reading you have probably noticed that there is a lot of redundancy. This is partly because the messages are generated by different components in the runtime - the VM, the x86 JIT, and the x64 JIT - which were developed, and have evolved, fairly independently. There is also some amount of redundancy as a safety precaution.
Grant RIchinsCLR Codegen Team