in src/WebJobs.Script.WebHost/PreJIT/JitTraceRuntime.cs [81:263]
public static void Prepare(StreamReader jittraceStream, out int successfulPrepares, out int failedPrepares)
{
const string outerCsvEscapeChar = "~";
const string innerCsvEscapeChar = ":";
char[] outerCsvEscapeCharArray = new char[] { '~' };
char[] innerCsvEscapeCharArray = new char[] { ':' };
successfulPrepares = 0;
failedPrepares = 0;
while (true)
{
string methodString = string.Empty;
try
{
methodString = jittraceStream.ReadLine();
if (string.IsNullOrWhiteSpace(methodString))
{
break;
}
string[] methodStrComponents = SplitAndUnescape(methodString, outerCsvEscapeChar, outerCsvEscapeCharArray);
Type owningType = Type.GetType(methodStrComponents[1], false);
// owningType failed to load above. Skip rest of method discovery
if (owningType == null)
{
failedPrepares++;
LogOnFailure(methodString);
continue;
}
int signatureLen = int.Parse(methodStrComponents[2]);
string[] methodInstantiationArgComponents = SplitAndUnescape(methodStrComponents[3], innerCsvEscapeChar, innerCsvEscapeCharArray);
int genericMethodArgCount = int.Parse(methodInstantiationArgComponents[0]);
Type[] methodArgs = genericMethodArgCount != 0 ? new Type[genericMethodArgCount] : Array.Empty<Type>();
bool abortMethodDiscovery = false;
for (int iMethodArg = 0; iMethodArg < genericMethodArgCount; iMethodArg++)
{
Type methodArg = Type.GetType(methodInstantiationArgComponents[1 + iMethodArg], false);
methodArgs[iMethodArg] = methodArg;
// methodArg failed to load above. Skip rest of method discovery
if (methodArg == null)
{
abortMethodDiscovery = true;
break;
}
}
if (abortMethodDiscovery)
{
failedPrepares++;
LogOnFailure(methodString);
continue;
}
string methodName = methodStrComponents[4];
// Now all data is parsed
// Find method
IEnumerable<RuntimeMethodHandle> membersFound;
BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
if (methodName == ".ctor")
{
if (genericMethodArgCount != 0)
{
// Ctors with generic args don't make sense
failedPrepares++;
LogOnFailure(methodString);
continue;
}
membersFound = CtorMethodsThatMatch();
IEnumerable<RuntimeMethodHandle> CtorMethodsThatMatch()
{
ConstructorInfo[] constructors = owningType.GetConstructors(bindingFlags);
foreach (ConstructorInfo ci in constructors)
{
ConstructorInfo returnConstructorInfo = null;
try
{
if (ci.GetParameters().Length == signatureLen)
{
returnConstructorInfo = ci;
}
}
catch
{
}
if (returnConstructorInfo != null)
{
yield return returnConstructorInfo.MethodHandle;
}
}
}
}
else if (methodName == ".cctor")
{
MemberInfo mi = owningType.TypeInitializer;
if (mi == null)
{
// This type no longer has a type initializer
failedPrepares++;
LogOnFailure(methodString);
continue;
}
membersFound = new RuntimeMethodHandle[] { owningType.TypeInitializer.MethodHandle };
}
else
{
membersFound = MethodsThatMatch();
IEnumerable<RuntimeMethodHandle> MethodsThatMatch()
{
MethodInfo[] methods = owningType.GetMethods(bindingFlags);
foreach (MethodInfo mi in methods)
{
MethodInfo returnMethodInfo = null;
try
{
if (mi.Name != methodName)
{
continue;
}
if (mi.GetParameters().Length != signatureLen)
{
continue;
}
if (mi.GetGenericArguments().Length != genericMethodArgCount)
{
continue;
}
if (genericMethodArgCount != 0)
{
returnMethodInfo = mi.MakeGenericMethod(methodArgs);
}
else
{
returnMethodInfo = mi;
}
}
catch
{
}
if (returnMethodInfo != null)
{
yield return returnMethodInfo.MethodHandle;
}
}
}
}
bool foundAtLeastOneEntry = false;
foreach (RuntimeMethodHandle memberHandle in membersFound)
{
foundAtLeastOneEntry = true;
try
{
System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(memberHandle);
successfulPrepares++;
}
catch
{
failedPrepares++;
LogOnFailure(methodString);
}
}
if (!foundAtLeastOneEntry)
{
failedPrepares++;
LogOnFailure(methodString);
}
}
catch
{
failedPrepares++;
LogOnFailure(methodString);
}
}
}