前言
.NET9 PreView3发布了,它的CLR的改进主要是两个方面。
修改了CLR的异常处理,以期更快的速度
运行时查找共享泛型的内联改进
下面分别看下
异常
异常处理作为一个较为重要的CLR模块,在此次PreView3的改进中。微软重写了异常处理模块。这些模块的指令和平台包括了x64/arm64以及win/linux,但是同时因为没有经过充分的测试,且也有一些已知的错误。所以这里提供了一个如果遇到极端的错误,而目前没有修复,可以通过环境变量:
DOTNET_LegacyExceptionHandling==1 //1为回到旧有
System.Runtime.LegacyExceptionHandling //运行库
来对其进行恢复到之前旧有的异常处理,而屏蔽新的异常处理模块。这一块的代码,主要如下:
在实例化异常模块的句柄的时候,获取到以上环境变量值:
void InitializeExceptionHandling()
{
//此处省略一万行
g_isNewExceptionHandlingEnabled = Configuration::GetKnobBooleanValue(W("System.Runtime.LegacyExceptionHandling"), CLRConfig::EXTERNAL_LegacyExceptionHandling ) == 0;
//此处省略一万行
}
然后在进行异常处理的时候判断g_isNewExceptionHandlingEnabled值是否为true。
ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord,
IN PVOID pEstablisherFrame,
IN OUT PCONTEXT pContextRecord,
IN OUT PDISPATCHER_CONTEXT pDispatcherContext
)
{
STATIC_CONTRACT_MODE_ANY;
STATIC_CONTRACT_GC_TRIGGERS;
STATIC_CONTRACT_THROWS;
if (g_isNewExceptionHandlingEnabled)
{
//旧的模块处理程序
return ProcessCLRExceptionNew(pExceptionRecord, pEstablisherFrame, pContextRecord, pDispatcherContext);
}
//新的异常处理模块程序,一万行
}
可以看到以上逻辑很清晰了,如果环境变量值为true,则继续旧有的异常处理。如果为false,则进行新的异常模块处理调用。
内联
这点比较简单,设若如下代码:
static bool Test<T>() => Callee<T>();
static bool Callee<T>() => typeof(T) == typeof(int);
static void Main(string[] args)
{
bool l= Test<string>();
Console.ReadLine();
}
.NET9 Pre3之前,需要调用运行时以创建类型实例化以及字典查找类型,但是进行内联之后,在编译阶段即可形成如下代码,以提高性能:
原:
static bool Test<string>() => typeof(string) == typeof(int);
变:
static bool Test<string>() => false;
这里的创建类型实例化和字段查找类型怎么理解呢?在Test<T>()函数里,首先调用了一个运行时函数JIT_GenericHandleMethod,然后才调用Callee<T>()。前者最终调用的是JIT_GenericHandle_Framed,后者进行了实例化以及字段查找:
NOINLINE HCIMPL5(CORINFO_GENERIC_HANDLE, JIT_GenericHandle_Framed,
CORINFO_CLASS_HANDLE classHnd,
CORINFO_METHOD_HANDLE methodHnd,
LPVOID signature,
DWORD dictionaryIndexAndSlot,
CORINFO_MODULE_HANDLE moduleHnd)
{
CONTRACTL {
FCALL_CHECK;
PRECONDITION(classHnd != || methodHnd != );
PRECONDITION(classHnd == || methodHnd == );
} CONTRACTL_END;
CORINFO_GENERIC_HANDLE result = ;
MethodDesc * pMD = GetMethod(methodHnd);
MethodTable * pMT = TypeHandle(classHnd).AsMethodTable();
Module * pModule = GetModule(moduleHnd);
HELPER_METHOD_FRAME_BEGIN_RET_0();
result = JIT_GenericHandleWorker(pMD, pMT, signature, dictionaryIndexAndSlot, pModule);
HELPER_METHOD_FRAME_END();
_ASSERTE(result != );
return result;
}
而变化之后的可以在编译过程中计算该类型检查,因为string明显不是int类型,直接返回false
static bool Test<string>() => false;