Skip to main content
Version: Next

Retarget Metadata

Anonymous classes and anonymous functions generated by the compiler are unstable. Sometimes, simply adding a new type or function to an assembly can cause a large number of anonymous classes and functions to have their names changed. Even though the code of these anonymous classes themselves hasn't changed, because their names have changed, when generating dhao files, these anonymous classes and functions will be judged as changed, causing these anonymous functions to execute interpretively, ultimately affecting runtime performance.

Issues with Functions Marked with [BurstCompile]

If the game uses burst-related technology, burst-related packages will modify functions marked with [BurstCompile] during compilation, for example:


[BurstCompile]
private static int DecryptNumber(int number, int mulFactor, int addFactor)
{
return (number - addFactor) / mulFactor;
}

Will ultimately be compiled to:


[BurstCompile]
private static int DecryptNumber(int number, int mulFactor, int addFactor)
{
return DecryptNumber_00000029$BurstDirectCall.Invoke(number, mulFactor, addFactor);
}

public delegate int DecryptNumber_00000029$PostfixBurstDelegate(int number, int mulFactor, int addFactor);

internal static class DecryptNumber_00000029$BurstDirectCall
{

// Some code omitted ...

public unsafe static int Invoke(int number, int mulFactor, int addFactor)
{
if (BurstCompiler.IsEnabled)
{
IntPtr functionPointer = GetFunctionPointer();
if (functionPointer != (IntPtr)0)
{
return ((delegate* unmanaged[Cdecl]<int, int, int, int>)functionPointer)(number, mulFactor, addFactor);
}
}
return DecryptNumber$BurstManaged(number, mulFactor, addFactor);
}
}


If you add some other types to the assembly, even without modifying the code of DecryptNumber, during the next compilation, DecryptNumber_00000029$BurstDirectCall and DecryptNumber_00000029$PostfixBurstDelegate might become DecryptNumber_0000002A$BurstDirectCall and DecryptNumber_0000002A$PostfixBurstDelegate.

This not only causes DecryptNumber to incorrectly execute interpretively, but in HybridCLR versions below 7.4.0, it may even cause runtime errors or crashes!

Retarget Anonymous Type Names and Anonymous Function Names

Starting from Ultimate version v7.4.0, HybridCLR.Editor.AssemblyMetaRetarget is provided for retargeting metadata to enhance the stability of metadata related to anonymous classes and anonymous functions.

Usage is as follows:

        private static void RetargetAssembly()
{
string dllName = "HotUpdate";

string dllDir = $"{Application.dataPath}/../Dlls";

string oldDllFile = $"{dllDir}/{dllName}.old.dll.bytes";
string newDllFile = $"{dllDir}/{dllName}.new.dll.bytes";
byte[] oldDllBytes = File.ReadAllBytes(oldDllFile);
byte[] newDllBytes = File.ReadAllBytes(newDllFile);

var retarget = new AssemblyMetaRetarget(oldDllBytes, newDllBytes);
retarget.Retarget();
retarget.Save($"{dllDir}/{dllName}.retargeted.dll.bytes");
}

Other Notes

Retargeting metadata is optional. If you don't use [BurstCompile], this operation is generally not needed.

Please use the generated assembly as the latest hot update assembly after retargeting metadata, for generating dhao files.