test: replace render leaf source freezes
This commit is contained in:
parent
3c492aedc2
commit
5e56045077
3 changed files with 378 additions and 214 deletions
|
|
@ -9,6 +9,10 @@ internal readonly record struct CompiledFieldReference(
|
|||
int Offset,
|
||||
OpCode OpCode,
|
||||
FieldInfo Field);
|
||||
internal readonly record struct CompiledBranch(
|
||||
int Offset,
|
||||
OpCode OpCode,
|
||||
int TargetOffset);
|
||||
|
||||
/// <summary>
|
||||
/// Reads compiled call/new-object edges from a method body. Architecture tests
|
||||
|
|
@ -146,6 +150,40 @@ internal static class CompiledCallGraph
|
|||
return references;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads short and long branch destinations. Tests use this to prove that
|
||||
/// an optional dependency guard jumps around a construction edge without
|
||||
/// freezing the source expression that produced the branch.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<CompiledBranch> ReadBranches(MethodBase method)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(method);
|
||||
byte[] il = method.GetMethodBody()?.GetILAsByteArray()
|
||||
?? throw new InvalidOperationException(
|
||||
$"{method.DeclaringType?.FullName}.{method.Name} has no compiled body.");
|
||||
var branches = new List<CompiledBranch>();
|
||||
|
||||
for (int cursor = 0; cursor < il.Length;)
|
||||
{
|
||||
int instructionOffset = cursor;
|
||||
OpCode opCode = ReadOpCode(il, ref cursor);
|
||||
if (opCode.OperandType == OperandType.ShortInlineBrTarget)
|
||||
{
|
||||
int target = cursor + sizeof(sbyte) + unchecked((sbyte)il[cursor]);
|
||||
branches.Add(new CompiledBranch(instructionOffset, opCode, target));
|
||||
}
|
||||
else if (opCode.OperandType == OperandType.InlineBrTarget)
|
||||
{
|
||||
int target = cursor + sizeof(int) + BitConverter.ToInt32(il, cursor);
|
||||
branches.Add(new CompiledBranch(instructionOffset, opCode, target));
|
||||
}
|
||||
|
||||
cursor += OperandSize(opCode.OperandType, il, cursor);
|
||||
}
|
||||
|
||||
return branches;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads types named by compiled type operands such as casts, boxing, and
|
||||
/// <c>isinst</c>. This lets tests retain an exact type boundary without
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue