Each method's life have 3 stages:
metadata record, no code at all; - before calling "compile_method, that called GetFunctionPointer() in managed;
code filled with trampolines; - before calling method at least once
actual code with actual references; - after method actually completed at least once
Dynamic methods are not any special, when method is compiled, it's still filled with trampolines and calling trampoline cause runtime to update call site.
As far as i remember, runtime always emit trampolines, ever if have compiled version of method in cache.
RuntimeHelpers.PrepareMethod(targetMethod.MethodHandle);
and all code changes related to this method, well, i have bad news for you
[MonoTODO("Currently a no-op")]
public static void PrepareMethod (RuntimeMethodHandle method)
{
}
[MonoTODO("Currently a no-op")]
public static void PrepareMethod (RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation)
{
}
Fetching x86 for this method from game will give you noop function also.
All core related to usege of preparemethod is invalid for mono runtime.
Code allocated for functions, allocated from native pool, not heap, in addition, it's permanent and never deallocated, ever if dynamic method is lost, it's data will stay as long as domain hosting data alive.
To detect why and how, just "protect" dynamic method memory from writing with virtual protect, and you will see trace with method name\chain that caused modification.