Fix catch clauses referring to a generic method argument (#6895)

* Fix catch clauses referring to a generic method argument

Scrutinizing the CoreCLR Pri#1 results I found a large bucket of
failures caused by mismatched catch clauses for generic exception
types. With tons of help from Jan Vorlicek I tracked this down to
a subtle difference in getMethodInfo flags. I have added one of
the previously failing Pri#1 tests to the CPAOT trivial unit test
suite.

* Set up the method flags unconditionally per JanK's PR feedback

I have audited the corresponding Crossgen code and I must admit
Jan Kotas is right as always - the extra method flags should be set
no matter whether the R2R build mode is active.
This commit is contained in:
Tomáš Rylek 2019-01-26 19:23:29 +01:00 коммит произвёл Jan Kotas
Родитель 00bf204a90
Коммит 67895ecaee
2 изменённых файлов: 93 добавлений и 1 удалений

Просмотреть файл

@ -394,8 +394,21 @@ namespace Internal.JitInterface
methodInfo->maxStack = (uint)methodIL.MaxStack;
methodInfo->EHcount = (uint)methodIL.GetExceptionRegions().Length;
methodInfo->options = methodIL.IsInitLocals ? CorInfoOptions.CORINFO_OPT_INIT_LOCALS : (CorInfoOptions)0;
methodInfo->regionKind = CorInfoRegionKind.CORINFO_REGION_NONE;
if (method.AcquiresInstMethodTableFromThis())
{
methodInfo->options |= CorInfoOptions.CORINFO_GENERICS_CTXT_FROM_THIS;
}
else if (method.RequiresInstMethodDescArg())
{
methodInfo->options |= CorInfoOptions.CORINFO_GENERICS_CTXT_FROM_METHODDESC;
}
else if (method.RequiresInstMethodTableArg())
{
methodInfo->options |= CorInfoOptions.CORINFO_GENERICS_CTXT_FROM_METHODTABLE;
}
methodInfo->regionKind = CorInfoRegionKind.CORINFO_REGION_NONE;
Get_CORINFO_SIG_INFO(method, &methodInfo->args);
Get_CORINFO_SIG_INFO(methodIL.GetLocals(), &methodInfo->locals);

Просмотреть файл

@ -431,6 +431,84 @@ internal class Program
}
}
private class GenException<T> : Exception {}
private static bool GenericTryCatch<T>()
{
Exception thrown = new GenException<T>();
try
{
throw thrown;
}
catch (GenException<T>)
{
return true;
}
catch (Exception ex)
{
Console.WriteLine("Caught {0} (expected {1})", ex.GetType(), thrown.GetType());
return false;
}
}
private class RefX1<T> {}
private class RefX2<T,U> {}
private struct ValX1<T> {}
private struct ValX2<T,U> {}
private struct ValX3<T,U,V>{}
private static bool GenericTryCatchTest()
{
bool success = true;
success = GenericTryCatch<double>() && success;
success = GenericTryCatch<string>() && success;
success = GenericTryCatch<object>() && success;
success = GenericTryCatch<Guid>() && success;
success = GenericTryCatch<int[]>() && success;
success = GenericTryCatch<double[,]>() && success;
success = GenericTryCatch<string[][][]>() && success;
success = GenericTryCatch<object[,,,]>() && success;
success = GenericTryCatch<Guid[][,,,][]>() && success;
success = GenericTryCatch<RefX1<int>[]>() && success;
success = GenericTryCatch<RefX1<double>[,]>() && success;
success = GenericTryCatch<RefX1<string>[][][]>() && success;
success = GenericTryCatch<RefX1<object>[,,,]>() && success;
success = GenericTryCatch<RefX1<Guid>[][,,,][]>() && success;
success = GenericTryCatch<RefX2<int,int>[]>() && success;
success = GenericTryCatch<RefX2<double,double>[,]>() && success;
success = GenericTryCatch<RefX2<string,string>[][][]>() && success;
success = GenericTryCatch<RefX2<object,object>[,,,]>() && success;
success = GenericTryCatch<RefX2<Guid,Guid>[][,,,][]>() && success;
success = GenericTryCatch<ValX1<int>[]>() && success;
success = GenericTryCatch<ValX1<double>[,]>() && success;
success = GenericTryCatch<ValX1<string>[][][]>() && success;
success = GenericTryCatch<ValX1<object>[,,,]>() && success;
success = GenericTryCatch<ValX1<Guid>[][,,,][]>() && success;
success = GenericTryCatch<ValX2<int,int>[]>() && success;
success = GenericTryCatch<ValX2<double,double>[,]>() && success;
success = GenericTryCatch<ValX2<string,string>[][][]>() && success;
success = GenericTryCatch<ValX2<object,object>[,,,]>() && success;
success = GenericTryCatch<ValX2<Guid,Guid>[][,,,][]>() && success;
success = GenericTryCatch<ValX1<int>>() && success;
success = GenericTryCatch<ValX1<RefX1<int>>>() && success;
success = GenericTryCatch<ValX2<int,string>>() && success;
success = GenericTryCatch<ValX3<int,string,Guid>>() && success;
success = GenericTryCatch<ValX1<ValX1<int>>>() && success;
success = GenericTryCatch<ValX1<ValX1<ValX1<string>>>>() && success;
success = GenericTryCatch<ValX1<ValX1<ValX1<ValX1<Guid>>>>>() && success;
success = GenericTryCatch<ValX1<ValX2<int,string>>>() && success;
success = GenericTryCatch<ValX2<ValX2<ValX1<int>,ValX3<int,string, ValX1<ValX2<int,string>>>>,ValX2<ValX1<int>,ValX3<int,string, ValX1<ValX2<int,string>>>>>>() && success;
success = GenericTryCatch<ValX3<ValX1<int[][,,,]>,ValX2<object[,,,][][],Guid[][][]>,ValX3<double[,,,,,,,,,,],Guid[][][][,,,,][,,,,][][][],string[][][][][][][][][][][]>>>();
return success;
}
private static bool FileStreamNullRefTryCatch()
{
try
@ -869,6 +947,7 @@ internal class Program
RunTest("EmptyArrayOfString", EmptyArrayOfString());
RunTest("EnumerateEmptyArrayOfString", EnumerateEmptyArrayOfString());
RunTest("TryCatch", TryCatch());
RunTest("GenericTryCatchTest", GenericTryCatchTest());
RunTest("FileStreamNullRefTryCatch", FileStreamNullRefTryCatch());
RunTest("InstanceMethodTest", InstanceMethodTest());
RunTest("ThisObjGenericLookupTest", ThisObjGenericLookupTest());