I am creating a system to store value types(int, byte, structs) on the heap and in order to prevent boxing and unboxing of said value types. This is because all of the constant boxing and unboxing in the Unity 3D engine is creating large GC CPU spikes in our large code base.
VerificationException: Operation could destabilize the runtime.
The above exception is thrown when I try to invoke the dynamic method. The stack trace ends just before it goes into the dynamic method and it's not possible to break point the execution. More information is given in the example below.
void Main()
{
var fieldInfo = typeof(MyClass).GetMember("Number")[0] as FieldInfo;
var pointerSetFunc = CreatePointerFieldSetMethod(fieldInfo);
object myClass = new MyClass();
// The exception occurs when invoking the dynamic method.
pointerSetFunc(myClass, 0);
}
public class MyClass
{
public byte Number;
}
public static Action<object, int> CreatePointerFieldSetMethod(FieldInfo field)
{
var setMethod = new DynamicMethod("SetFieldFromPointer", typeof(void), new[] { typeof(object), typeof(int) }, true);
ILGenerator generator = setMethod.GetILGenerator();
// This returns the correct value. byte CustomBox<byte>.Unbox(Int32 index);
var unboxFunc = typeof(CustomBox<>).MakeGenericType(field.FieldType).GetMethod("Unbox", BindingFlags.Static | BindingFlags.Public);
// Somewhere in the below code the exception occurs.
generator.Emit(OpCodes.Ldarg_1); // This should be the index or "pointer" to pass into the CustomBox.Unbox function.
generator.EmitCall(OpCodes.Call, unboxFunc, null);
generator.Emit(OpCodes.Stloc_0); // This should be the result of unboxing.
// This code does not get called.
generator.Emit(OpCodes.Ldarg_0); // This should be the object MyClass.
generator.Emit(OpCodes.Ldloc_0); // This should be the value received from the CustomBox.Unbox function.
generator.Emit(OpCodes.Stfld, field); // Set the MyClass.Number field.
generator.Emit(OpCodes.Ret);
return (Action<object, int>)setMethod.CreateDelegate(typeof(Action<object, int>));
}
// The point of this class is to store values types (int, byte, struct, etc..) in an array already on the heap to avoid boxing.
// Boxing has become an issue on our application.
public struct CustomBox<T> where T : struct
{
public static T Unbox(int index)
{
// TODO: Actually make the unbox code.
return default(T);
}
}
Edit:
Heres the method I'm trying to create and it's generated IL:
private static void SetFieldUsingIndex(object myClass, int index)
{
byte number = Values<byte>.Unbox(index);
((MyClass)myClass).Number = number;
}
/* Generated IL for above method.
IL_0000: nop
IL_0001: ldarg.1
IL_0002: call !0 class CPURaceTest.Values`1<uint8>::Unbox(int32)
IL_0007: stloc.0
IL_0008: ldarg.0
IL_0009: castclass CPURaceTest.MyClass
IL_000e: ldloc.0
IL_000f: stfld uint8 CPURaceTest.MyClass::Number
IL_0014: ret
*/
Copyright Notice:Content Author:「Tristan C」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/40901221/verificationexception-operation-could-destabilize-the-runtime-troubles-with-em