Skip to content

Instantly share code, notes, and snippets.

@Nihlus
Created September 29, 2018 18:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nihlus/f24fadde955768c9fbb7978fc040c694 to your computer and use it in GitHub Desktop.
Save Nihlus/f24fadde955768c9fbb7978fc040c694 to your computer and use it in GitHub Desktop.
/// <inheritdoc/>
public override void EmitPrologue(ILGenerator il, PipelineWorkUnit<IntrospectiveMethodInfo> workUnit)
{
var definition = workUnit.Definition;
// Create the argument list as an array
var argumentArray = il.DeclareLocal(typeof(object[]));
il.EmitConstantInt(definition.ParameterTypes.Count);
il.EmitNewArray<object>();
for (short i = 1; i <= definition.ParameterTypes.Count; ++i)
{
var parameterType = definition.ParameterTypes[i];
il.EmitLoadLocalVariable(argumentArray);
il.EmitLoadArgument(i);
if (parameterType.IsGenericParameter)
{
// Check constraints for boxing needs
if (!parameterType.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint))
{
il.EmitBox(parameterType);
}
}
else if (parameterType.IsValueType)
{
il.EmitBox(parameterType);
}
il.EmitSetArrayElement<object>();
}
// Create a local to hold the method's introspective signature
var methodInfoLocal = il.DeclareLocal(typeof(IntrospectiveMethodInfo));
// Create a new introspective method info for the current method
il.EmitCallDirect<MethodBase>(nameof(MethodBase.GetCurrentMethod));
il.EmitNewObject(typeof(IntrospectiveMethodInfo).GetConstructor(new[] { typeof(MethodInfo) }));
il.EmitSetLocalVariable(methodInfoLocal);
// Check if we have a created implementation
var trueCase = il.DefineLabel();
il.EmitLoadField(_genericJitEmitter);
il.EmitLoadLocalVariable(methodInfoLocal);
il.EmitCallDirect<JustInTimeGenericEmitter>(nameof(JustInTimeGenericEmitter.HasClosedImplementation));
il.EmitBranchTrue(trueCase);
// If not, create one
il.EmitLoadField(_genericJitEmitter);
il.EmitLoadLocalVariable(methodInfoLocal);
il.EmitLoadArgument(0);
// ReSharper disable once PossibleNullReferenceException
il.EmitCallDirect(typeof(NativeLibraryBase).GetProperty(nameof(NativeLibraryBase.LibraryPath)).GetMethod);
il.EmitCallDirect<JustInTimeGenericEmitter>(nameof(JustInTimeGenericEmitter.CreateClosedImplementation));
// Then grab the closed implementation
il.MarkLabel(trueCase);
// Create invocation parameters
il.EmitLoadField(_genericJitEmitter);
il.EmitLoadLocalVariable(methodInfoLocal);
il.EmitCallDirect<JustInTimeGenericEmitter>(nameof(JustInTimeGenericEmitter.GetClosedImplementationMethodPointer));
il.EmitLoadField(_genericJitEmitter);
il.EmitLoadLocalVariable(methodInfoLocal);
il.EmitCallDirect<JustInTimeGenericEmitter>(nameof(JustInTimeGenericEmitter.GetClosedImplementationTypeInstance));
il.EmitLoadLocalVariable(argumentArray);
// And finally, invoke it
il.EmitCallDirect<MethodInfo>(nameof(MethodInfo.Invoke), typeof(object), typeof(object[]));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment