Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2017-01-20 00:36:23 +0300
committerGitHub <noreply@github.com>2017-01-20 00:36:23 +0300
commit7f4560bdec0c33ff4f5805cb2fe6f2814b0a7e67 (patch)
tree75f6f7029c38ea91cb9ae38f90137bc8a51cbb56
parent5d09edbe157e9a5cbfb33b76ba28f6548c28a2d8 (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.cs7
-rw-r--r--tests/src/Simple/Generics/Generics.cs37
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
//