Using a clever hack is always risky. Previously I described how to use the ldftn
and ldvirtftn
CIL instructions to detect if a method is overriden by a subclass. It turns out that there is a problem with this trick. If the method containing the ldftn
instruction is JITted before the method it refers to, the method pointer returned (and burned into the generated code) is the JIT stub, when the method subsequently is JITted the new function pointer is stored in the vtable of subsequently loaded subclasses and the detection method yields a false positive.
Here's a small C# demo that demonstrates an equivalent effect:
using System;
using System.Runtime.CompilerServices;
class Program {
static void Main() {
RuntimeMethodHandle m = typeof(Program).GetMethod("Foo").MethodHandle;
//RuntimeHelpers.PrepareMethod(m);
Console.WriteLine(m.GetFunctionPointer());
new Program().Foo();
Console.WriteLine(m.GetFunctionPointer());
}
public virtual void Foo() { }
}
When you run this program on .NET, it prints out two different values. One possible solution is present in the commented out line, if you uncomment that the two pointer values printed will be the same, because PrepareMethod
forces the method to be JIT compiled.
Another slightly more robust method is to avoid ldftn
and use ldvirtftn
to get the base method as well. The downside is that you need to have an instance of an object of a class that does not override the method in question.
Finally, if you want to use this approach consider using this as an optimization and if this detection is positive, use reflection to confirm.