// Avoid potential extra work for the return (for example, vzeroupper)
call->gtType = TYP_VOID;
+ // The runtime requires that we perform a null check on the `this` argument before
+ // tail calling to a virtual dispatch stub. This requirement is a consequence of limitations
+ // in the runtime's ability to map an AV to a NullReferenceException if
+ // the AV occurs in a dispatch stub that has unmanaged caller.
+ if (call->IsVirtualStub())
+ {
+ call->gtFlags |= GTF_CALL_NULLCHECK;
+ }
+
// Do some target-specific transformations (before we process the args,
// etc.) for the JIT helper case.
if (tailCallViaJitHelper)
JITDUMP("fgMorphTailCallViaJitHelper (before):\n");
DISPTREE(call);
- // The runtime requires that we perform a null check on the `this` argument before
- // tail calling to a virtual dispatch stub. This requirement is a consequence of limitations
- // in the runtime's ability to map an AV to a NullReferenceException if
- // the AV occurs in a dispatch stub that has unmanaged caller.
- if (call->IsVirtualStub())
- {
- call->gtFlags |= GTF_CALL_NULLCHECK;
- }
-
// For the helper-assisted tail calls, we need to push all the arguments
// into a single list, and then add a few extra at the beginning or end.
//
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+public class Runtime_61486
+{
+ public static int Main()
+ {
+ var my = new My(new My(null));
+ var m = my.GetType().GetMethod("M");
+ try
+ {
+ m.Invoke(my, null);
+ return -1;
+ }
+ catch (TargetInvocationException ex) when (ex.InnerException is NullReferenceException)
+ {
+ return 100;
+ }
+ }
+
+ public interface IFace
+ {
+ void M();
+ }
+
+ public class My : IFace
+ {
+ private IFace _face;
+
+ public My(IFace face)
+ {
+ _face = face;
+ }
+
+ // We cannot handle a null ref inside a VSD if the caller is not
+ // managed frame. This test is verifying that JIT null checks ahead of
+ // time in this case.
+ [MethodImpl(MethodImplOptions.AggressiveOptimization)]
+ public void M() => _face.M();
+ }
+}