Skip to content

Commit

Permalink
Redo method devirtualization for ldvirtftn
Browse files Browse the repository at this point in the history
  • Loading branch information
BadRyuner committed Jun 7, 2024
1 parent cb6db0e commit 4214f1a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ private static CilDispatchResult Invoke(CilExecutionContext context, IMethodDesc
}
}

protected static MethodDefinition? FindMethodImplementationInType(TypeDefinition? type, MethodDefinition? baseMethod)
internal static MethodDefinition? FindMethodImplementationInType(TypeDefinition? type, MethodDefinition? baseMethod)
{
if (type is null || baseMethod is null || !baseMethod.IsVirtual)
return baseMethod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,34 @@ protected override CilDispatchResult DispatchInternal(CilExecutionContext contex
if (thisObjectType == null)
throw new CilEmulatorException("Unable to resolve the type of object");

var virtualFunction = ((IMethodDescriptor)instruction.Operand!);
var virtualFunctionName = virtualFunction.Name;
var virtualFunctionSignature = virtualFunction.Signature;

do
{
// try resolve function
var resolvedVirtualFunction = thisObjectType.Methods
.FirstOrDefault(method => method.Name == virtualFunctionName
&& SignatureComparer.Default.Equals(method.Signature, virtualFunctionSignature));

// if resolved then push function pointer
if (resolvedVirtualFunction != null)
{
var functionPointer = methods.GetAddress(resolvedVirtualFunction);
stack.Push(factory.CreateNativeInteger(functionPointer), type);
return CilDispatchResult.Success();
}

// else switch to BaseType and try resolve again
thisObjectType = thisObjectType.BaseType?.Resolve();
} // or exit and throw CilEmulationException
while (thisObjectType != null);

throw new CilEmulatorException($"Unable to resolve a virtual function for type {thisObjectType!.FullName}");
var virtualFunction = (IMethodDescriptor)instruction.Operand!;

IMethodDescriptor? implementation = CallHandlerBase.FindMethodImplementationInType(thisObjectType, virtualFunction.Resolve());

if (implementation == null)
{
return CilDispatchResult.Exception(
context.Machine.Heap.AllocateObject(
context.Machine.ValueFactory.MissingMethodExceptionType,
true)
.AsObjectHandle(context.Machine)
);
}

// Instantiate any generics.
var genericContext = GenericContext.FromMethod(virtualFunction);
if (!genericContext.IsEmpty)
{
var instantiated = thisObjectType
.CreateMemberReference(implementation.Name!, implementation.Signature!);

implementation = genericContext.Method != null
? instantiated.MakeGenericInstanceMethod(genericContext.Method.TypeArguments.ToArray())
: instantiated;
}

var functionPointer = methods.GetAddress(implementation);
stack.Push(factory.CreateNativeInteger(functionPointer), type);
return CilDispatchResult.Success();
}
}

0 comments on commit 4214f1a

Please sign in to comment.