Skip to content

Instantly share code, notes, and snippets.

@marijnz
Created April 14, 2020 08:09
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 marijnz/d5dedeced7e746280be29cf827d03404 to your computer and use it in GitHub Desktop.
Save marijnz/d5dedeced7e746280be29cf827d03404 to your computer and use it in GitHub Desktop.
private ModuleBuilder m_module;
[Test]
public void TestComp() {
/*
var assembly = AssemblyDefinitionFor(GetType());
var module = assembly.MainModule;
TypeDefinition cClass = new TypeDefinition(GetType().Namespace, "MyTestJob", TypeAttributes.Class);
//Class.BaseType = TypeSystem.Object;
module.Types.Add(cClass);
// System.Reflection.Emit.t
TypeBuilder.c*/
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("DelegateTypeFactory"), AssemblyBuilderAccess.RunAndCollect);
m_module = assembly.DefineDynamicModule("DelegateTypeFactory");
var result = GetType().Assembly.GetTypes().Where(t => t.Name.Contains("MyTestJob"));
Debug.Log("result: " + result.FirstOrDefault());
var act = (new Func<int, int>(_ => {
for (int i = 0; i < 10; i++) {
var k = 1 + 2;
}
return 1;
}));
var method = act.Method ;
//var delType = CreateDelegateType(method);
// Option 1
{
//var paramTypes = method.GetParameters().Select(p => p.ParameterType);
//var delType = Expression.GetDelegateType(paramTypes.Append(method.ReturnType).ToArray());
//var del = method.CreateDelegate(delType, act.Target);
//FunctionPointer<Delegate> l = BurstCompiler.CompileFunctionPointer(del);
}
{
// Option 2
//var delType = CreateDelegateType(method);
//var del = method.CreateDelegate(delType, act.Target);
//FunctionPointer<Delegate> l = BurstCompiler.CompileFunctionPointer(del);
}
//var job = new TestJob();
//var delType = CreateDelegateType(job.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public)[0]);
//var del = method.CreateDelegate(delType, job);
//FunctionPointer<Delegate> l = BurstCompiler.CompileFunctionPointer(del);
var job = new TestJob();
method = job.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public)[0];
var paramTypes = method.GetParameters().Select(p => p.ParameterType);
var delType = CreateDelegateType(job.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public)[0]);
var del = Delegate.CreateDelegate(delType, method);
var l = BurstCompiler.CompileFunctionPointer(del);
var inv = Marshal.GetDelegateForFunctionPointer(l.Value, delType);
var s = Stopwatch.StartNew();
inv.DynamicInvoke(new NativeArray<int>(10, Allocator.Persistent));
Debug.Log("took: " + s.Elapsed.TotalMilliseconds);
s.Restart();
del.DynamicInvoke(new NativeArray<int>(10, Allocator.Persistent));
Debug.Log("non burst took: " + s.Elapsed.TotalMilliseconds);
}
[BurstCompile]
class TestJob {
[BurstCompile]
public static void Execute(ref NativeArray<int> test) {
var s = 5;
for (int i = 0; i < 2000000; i++) {
s *= i;
}
}
}
private static Delegate CreateDelegate(MethodInfo method) {
var paramTypes = method.GetParameters().Select(p => p.ParameterType);
Type delegateType = Expression.GetDelegateType(paramTypes.Append(method.ReturnType).ToArray());
return Delegate.CreateDelegate(delegateType, method, true);
}
public Type CreateDelegateType(MethodInfo method)
{
string nameBase = string.Format("{0}{1}", method.DeclaringType.Name, method.Name);
string name = GetUniqueName(nameBase);
var typeBuilder = m_module.DefineType(
name, TypeAttributes.Sealed | TypeAttributes.Public, typeof(MulticastDelegate));
var constructor = typeBuilder.DefineConstructor(
MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public,
CallingConventions.Standard, new[] { typeof(object), typeof(IntPtr) });
constructor.SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
var parameters = method.GetParameters();
var invokeMethod = typeBuilder.DefineMethod(
"Invoke", MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public,
method.ReturnType, parameters.Select(p => p.ParameterType).ToArray());
invokeMethod.SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
for (int i = 0; i < parameters.Length; i++)
{
var parameter = parameters[i];
invokeMethod.DefineParameter(i + 1, ParameterAttributes.None, parameter.Name);
}
//invokeMethod.SetReturnType(method.ReturnType);
return typeBuilder.CreateType();
}
private string GetUniqueName(string nameBase)
{
int number = 2;
string name = nameBase;
while (m_module.GetType(name) != null)
name = nameBase + number++;
return name;
}
/*
protected AssemblyDefinition AssemblyDefinitionFor(Type type)
{
var assemblyLocation = type.Assembly.Location;
var ad = AssemblyDefinition.ReadAssembly(new MemoryStream(File.ReadAllBytes(assemblyLocation)));
return ad;
}
private MethodDefinition MakeExecuteMethod_Job()
{
MethodDefinition executeMethod = CecilHelpers.AddMethodImplementingInterfaceMethod(TypeDefinition.Module,
TypeDefinition, typeof(IJob).GetMethod(nameof(IJob.Execute)));
var executeIL = executeMethod.Body.GetILProcessor();
//executeIL.Emit(OpCodes.Ldarg_0);
executeIL.Emit(OpCodes.Call, ClonedLambdaBody);
//EmitCallToDeallocateOnCompletion(executeIL);
// executeIL.Emit(OpCodes.Ret);
return executeMethod;
}
public static MethodDefinition AddMethodImplementingInterfaceMethod(ModuleDefinition module, TypeDefinition type, System.Reflection.MethodInfo interfaceMethod)
{
var interfaceMethodReference = module.ImportReference(interfaceMethod);
var newMethod = new MethodDefinition(interfaceMethodReference.Name,
MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.Public |
MethodAttributes.HideBySig, interfaceMethodReference.ReturnType);
int index = 0;
foreach (var pd in interfaceMethodReference.Parameters)
{
var pdName = pd.Name;
if (pdName.Length == 0)
pdName = interfaceMethod.GetParameters()[index].Name;
newMethod.Parameters.Add(new ParameterDefinition(pdName, pd.Attributes, module.ImportReference(pd.ParameterType)));
index++;
}
type.Methods.Add(newMethod);
return newMethod;
}*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment