Skip to content

Commit b333573

Browse files
committed
poc for reuse
1 parent f4b1160 commit b333573

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

src/FastExpressionCompiler/TestTools.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ public static implicit operator TestContext(TestRun t)
591591
public bool Fail(string testName, int sourceLineNumber, AssertKind assertKind, string message)
592592
{
593593
#if DEBUG
594-
// When debugging raise the fail immediately as excpetion to avoid false sense of security
594+
// When debugging raise the fail immediately as exception to avoid false sense of security
595595
throw new AssertionException($"`{testName}` failed at line {sourceLineNumber}:{NewLine}{message}{NewLine}");
596596
#else
597597
TestRun.Failures.Add(new TestFailure(testName, sourceLineNumber, assertKind, message));

test/FastExpressionCompiler.IssueTests/EmitHacksTest.cs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,47 @@ public int Run()
2828

2929
void TryToReuseTheDynamicMethod(TestContext t)
3030
{
31-
t.Fail("TryToReuseTheDynamicMethod is not implemented yet");
31+
// Let's say there is a DynamicMethod of Func<int, int> returning its argument,
32+
// at the end I want to reuse the created DynamicMethod for another Func<int, int> returning arg + 42
33+
34+
var dynMethod = new DynamicMethod(string.Empty,
35+
typeof(int),
36+
[typeof(ExpressionCompiler.ArrayClosure), typeof(int)],
37+
typeof(ExpressionCompiler.ArrayClosure),
38+
true);
39+
40+
var il = dynMethod.GetILGenerator();
41+
42+
il.Emit(OpCodes.Ldarg_1);
43+
il.Emit(OpCodes.Ret);
44+
45+
var func = (Func<int, int>)dynMethod.CreateDelegate(typeof(Func<int, int>), ExpressionCompiler.EmptyArrayClosure);
46+
t.AreEqual(41, func(41));
47+
48+
// Reset the DynamicMethod internals that we need to reuse:
49+
// _ilGenerator = null;
50+
// _initLocals = true;
51+
// _methodHandle = null;
52+
var dynMethodType = dynMethod.GetType();
53+
var ilGeneratorField = dynMethodType.GetField("_ilGenerator", BindingFlags.Instance | BindingFlags.NonPublic);
54+
var initLocalsField = dynMethodType.GetField("_initLocals", BindingFlags.Instance | BindingFlags.NonPublic);
55+
var methodHandleField = dynMethodType.GetField("_methodHandle", BindingFlags.Instance | BindingFlags.NonPublic);
56+
57+
Console.WriteLine($"{{_ilGenerator: {ilGeneratorField?.GetValue(dynMethod) ?? "null"}, _initLocals: {initLocalsField.GetValue(dynMethod)}, _methodHandle: {methodHandleField?.GetValue(dynMethod) ?? "null"}}}");
58+
ilGeneratorField.SetValue(dynMethod, null);
59+
initLocalsField.SetValue(dynMethod, true);
60+
// methodHandleField.SetValue(dynMethod, null); // breaks the CLR
61+
62+
var il2 = dynMethod.GetILGenerator();
63+
64+
il2.Emit(OpCodes.Ldarg_1);
65+
il2.Emit(OpCodes.Ldc_I4, 42);
66+
il2.Emit(OpCodes.Add);
67+
il2.Emit(OpCodes.Ret);
68+
t.AreEqual(41, func(41));
69+
70+
var func2 = (Func<int, int>)dynMethod.CreateDelegate(typeof(Func<int, int>), ExpressionCompiler.EmptyArrayClosure);
71+
t.AreEqual(83, func2(41));
3272
}
3373

3474
public void DynamicMethod_Emit_Hack()

0 commit comments

Comments
 (0)