test: replace streaming source freezes
This commit is contained in:
parent
5a33369074
commit
0ad2ee1cdf
6 changed files with 436 additions and 285 deletions
|
|
@ -21,6 +21,69 @@ internal static class CompiledCallGraph
|
|||
.ToDictionary(opCode => opCode.Value);
|
||||
|
||||
public static IReadOnlyList<CompiledCall> Read(MethodBase method)
|
||||
=> ReadMethodReferences(method, includeDelegateTargets: false);
|
||||
|
||||
/// <summary>
|
||||
/// Reads calls, object construction, and method references used to build
|
||||
/// delegates. The latter lets lifetime tests inspect an operation manifest
|
||||
/// without invoking its real process/window resources.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<CompiledCall> ReadMethodReferences(MethodBase method) =>
|
||||
ReadMethodReferences(method, includeDelegateTargets: true);
|
||||
|
||||
public static IReadOnlyList<CompiledCall> ReadDeclared(Type type)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(type);
|
||||
const BindingFlags flags = BindingFlags.Instance
|
||||
| BindingFlags.Static
|
||||
| BindingFlags.Public
|
||||
| BindingFlags.NonPublic
|
||||
| BindingFlags.DeclaredOnly;
|
||||
return type.GetMethods(flags)
|
||||
.Cast<MethodBase>()
|
||||
.Concat(type.GetConstructors(flags))
|
||||
.Where(method => method.GetMethodBody() is not null)
|
||||
.SelectMany(Read)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static IReadOnlyList<string> ReadStringLiterals(MethodBase method)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(method);
|
||||
byte[] il = method.GetMethodBody()?.GetILAsByteArray()
|
||||
?? throw new InvalidOperationException(
|
||||
$"{method.DeclaringType?.FullName}.{method.Name} has no compiled body.");
|
||||
var literals = new List<string>();
|
||||
|
||||
for (int cursor = 0; cursor < il.Length;)
|
||||
{
|
||||
OpCode opCode = ReadOpCode(il, ref cursor);
|
||||
if (opCode == OpCodes.Ldstr)
|
||||
{
|
||||
int token = BitConverter.ToInt32(il, cursor);
|
||||
literals.Add(method.Module.ResolveString(token));
|
||||
}
|
||||
|
||||
cursor += OperandSize(opCode.OperandType, il, cursor);
|
||||
}
|
||||
|
||||
return literals;
|
||||
}
|
||||
|
||||
public static int IndexOf(
|
||||
IReadOnlyList<CompiledCall> calls,
|
||||
Type declaringType,
|
||||
string methodName,
|
||||
int startIndex = 0) =>
|
||||
Enumerable.Range(startIndex, calls.Count - startIndex)
|
||||
.FirstOrDefault(
|
||||
index => calls[index].Target.DeclaringType == declaringType
|
||||
&& calls[index].Target.Name == methodName,
|
||||
-1);
|
||||
|
||||
private static IReadOnlyList<CompiledCall> ReadMethodReferences(
|
||||
MethodBase method,
|
||||
bool includeDelegateTargets)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(method);
|
||||
byte[] il = method.GetMethodBody()?.GetILAsByteArray()
|
||||
|
|
@ -45,11 +108,13 @@ internal static class CompiledCallGraph
|
|||
token,
|
||||
declaringArguments,
|
||||
methodArguments);
|
||||
if (target is not null && opCode is { Value: var value }
|
||||
&& value is 0x28 or 0x6F or 0x73)
|
||||
{
|
||||
bool invocation = opCode == OpCodes.Call
|
||||
|| opCode == OpCodes.Callvirt
|
||||
|| opCode == OpCodes.Newobj;
|
||||
bool delegateTarget = includeDelegateTargets
|
||||
&& (opCode == OpCodes.Ldftn || opCode == OpCodes.Ldvirtftn);
|
||||
if (target is not null && (invocation || delegateTarget))
|
||||
calls.Add(new CompiledCall(instructionOffset, target));
|
||||
}
|
||||
}
|
||||
|
||||
cursor += OperandSize(opCode.OperandType, il, cursor);
|
||||
|
|
@ -58,17 +123,6 @@ internal static class CompiledCallGraph
|
|||
return calls;
|
||||
}
|
||||
|
||||
public static int IndexOf(
|
||||
IReadOnlyList<CompiledCall> calls,
|
||||
Type declaringType,
|
||||
string methodName,
|
||||
int startIndex = 0) =>
|
||||
Enumerable.Range(startIndex, calls.Count - startIndex)
|
||||
.FirstOrDefault(
|
||||
index => calls[index].Target.DeclaringType == declaringType
|
||||
&& calls[index].Target.Name == methodName,
|
||||
-1);
|
||||
|
||||
private static OpCode ReadOpCode(byte[] il, ref int cursor)
|
||||
{
|
||||
byte first = il[cursor++];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue