Created
April 14, 2020 08:09
-
-
Save marijnz/d5dedeced7e746280be29cf827d03404 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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