diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2017-01-20 00:36:23 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-20 00:36:23 +0300 |
commit | 7f4560bdec0c33ff4f5805cb2fe6f2814b0a7e67 (patch) | |
tree | 75f6f7029c38ea91cb9ae38f90137bc8a51cbb56 | |
parent | 5d09edbe157e9a5cbfb33b76ba28f6548c28a2d8 (diff) |
Fix handling of constrained method calls from shared generic code (#2527)
Don't track runtime determined dependencies if we're generating a call
to a constrained method.
The more complicated case is tracked in #2526.
-rw-r--r-- | src/JitInterface/src/CorInfoImpl.cs | 7 | ||||
-rw-r--r-- | tests/src/Simple/Generics/Generics.cs | 37 |
2 files changed, 43 insertions, 1 deletions
diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs index 2064ed4de..89b8d6a7a 100644 --- a/src/JitInterface/src/CorInfoImpl.cs +++ b/src/JitInterface/src/CorInfoImpl.cs @@ -2659,7 +2659,11 @@ namespace Internal.JitInterface // to abort the inlining attempt if the inlinee does any generic lookups. bool inlining = contextMethod != MethodBeingCompiled; - if (targetMethod.IsSharedByGenericInstantiations && !inlining) + // If we resolved a constrained call, calling GetRuntimeDeterminedObjectForToken below would + // result in getting back the unresolved target. Don't capture runtime determined dependencies + // in that case and rely on the dependency analysis computing them based on seeing a call to the + // canonical method body. + if (targetMethod.IsSharedByGenericInstantiations && !inlining && !resolvedConstraint) { MethodDesc runtimeDeterminedMethod = (MethodDesc)GetRuntimeDeterminedObjectForToken(ref pResolvedToken); pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle( @@ -2667,6 +2671,7 @@ namespace Internal.JitInterface } else { + Debug.Assert(!forceUseRuntimeLookup); pResult.codePointerOrStubLookup.constLookup.addr = (void*)ObjectToHandle( _compilation.NodeFactory.MethodEntrypoint(targetMethod)); } diff --git a/tests/src/Simple/Generics/Generics.cs b/tests/src/Simple/Generics/Generics.cs index e4fc32932..603d5b792 100644 --- a/tests/src/Simple/Generics/Generics.cs +++ b/tests/src/Simple/Generics/Generics.cs @@ -18,6 +18,7 @@ class Program TestDelegateVirtualMethod.Run(); TestDelegateInterfaceMethod.Run(); TestThreadStaticFieldAccess.Run(); + TestConstrainedMethodCalls.Run(); TestNameManglingCollisionRegression.Run(); TestUnusedGVMsDoNotCrashCompiler.Run(); @@ -383,6 +384,42 @@ class Program } } + class TestConstrainedMethodCalls + { + interface IFoo<T> + { + void Frob(); + } + + struct Foo<T> : IFoo<T> + { + public int FrobbedValue; + + public void Frob() + { + FrobbedValue = 12345; + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void DoFrob<T, U>(ref T t) where T : IFoo<U> + { + // Perform a constrained interface call from shared code. + // This should have been resolved to a direct call at compile time. + t.Frob(); + } + + public static void Run() + { + var foo = new Foo<object>(); + DoFrob<Foo<object>, object>(ref foo); + + // If the FrobbedValue doesn't change when we frob, we must have done box+interface call. + if (foo.FrobbedValue != 12345) + throw new Exception(); + } + } + // // Regression test for issue https://github.com/dotnet/corert/issues/1964 // |