test: replace runtime root source freezes
This commit is contained in:
parent
80c7b44457
commit
3c492aedc2
4 changed files with 248 additions and 220 deletions
|
|
@ -5,6 +5,10 @@ namespace AcDream.App.Tests.Architecture;
|
|||
|
||||
internal readonly record struct CompiledCall(int Offset, MethodBase Target);
|
||||
internal readonly record struct CompiledInstruction(int Offset, OpCode OpCode);
|
||||
internal readonly record struct CompiledFieldReference(
|
||||
int Offset,
|
||||
OpCode OpCode,
|
||||
FieldInfo Field);
|
||||
|
||||
/// <summary>
|
||||
/// Reads compiled call/new-object edges from a method body. Architecture tests
|
||||
|
|
@ -96,6 +100,52 @@ internal static class CompiledCallGraph
|
|||
return instructions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads compiled field loads and stores with their instruction offsets.
|
||||
/// This supports lifetime/state-order checks whose observable contract is
|
||||
/// a latch edge rather than a source spelling.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<CompiledFieldReference> ReadFieldReferences(
|
||||
MethodBase method)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(method);
|
||||
byte[] il = method.GetMethodBody()?.GetILAsByteArray()
|
||||
?? throw new InvalidOperationException(
|
||||
$"{method.DeclaringType?.FullName}.{method.Name} has no compiled body.");
|
||||
Type[]? declaringArguments = method.DeclaringType?.IsGenericType == true
|
||||
? method.DeclaringType.GetGenericArguments()
|
||||
: null;
|
||||
Type[]? methodArguments = method.IsGenericMethod
|
||||
? method.GetGenericArguments()
|
||||
: null;
|
||||
var references = new List<CompiledFieldReference>();
|
||||
|
||||
for (int cursor = 0; cursor < il.Length;)
|
||||
{
|
||||
int instructionOffset = cursor;
|
||||
OpCode opCode = ReadOpCode(il, ref cursor);
|
||||
if (opCode.OperandType == OperandType.InlineField)
|
||||
{
|
||||
int token = BitConverter.ToInt32(il, cursor);
|
||||
FieldInfo? field = method.Module.ResolveField(
|
||||
token,
|
||||
declaringArguments,
|
||||
methodArguments);
|
||||
if (field is not null)
|
||||
{
|
||||
references.Add(new CompiledFieldReference(
|
||||
instructionOffset,
|
||||
opCode,
|
||||
field));
|
||||
}
|
||||
}
|
||||
|
||||
cursor += OperandSize(opCode.OperandType, il, cursor);
|
||||
}
|
||||
|
||||
return references;
|
||||
}
|
||||
|
||||
/// <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