Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
dotNET Platform
runtime
提交
a08fec66
R
runtime
项目概览
dotNET Platform
/
runtime
12 个月 前同步成功
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
runtime
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
a08fec66
编写于
2月 12, 2021
作者:
E
Egor Bogatov
提交者:
GitHub
2月 12, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[RyuJIT] Devirtualize Comparer<T>.Default (#48160)
上级
3844c76b
变更
29
展开全部
隐藏空白更改
内联
并排
Showing
29 changed file
with
672 addition
and
170 deletion
+672
-170
src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs
...oreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs
+1
-1
src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h
src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h
+1
-0
src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
...oreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
+17
-0
src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h
src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h
+6
-1
src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
.../ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
+10
-0
src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
...lr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
+7
-0
src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
...clr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
+6
-0
src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp
src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp
+9
-0
src/coreclr/inc/corinfo.h
src/coreclr/inc/corinfo.h
+6
-0
src/coreclr/inc/icorjitinfoimpl_generated.h
src/coreclr/inc/icorjitinfoimpl_generated.h
+3
-0
src/coreclr/inc/jiteeversionguid.h
src/coreclr/inc/jiteeversionguid.h
+5
-5
src/coreclr/jit/ICorJitInfo_API_names.h
src/coreclr/jit/ICorJitInfo_API_names.h
+1
-0
src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
+9
-0
src/coreclr/jit/flowgraph.cpp
src/coreclr/jit/flowgraph.cpp
+4
-3
src/coreclr/jit/importer.cpp
src/coreclr/jit/importer.cpp
+15
-1
src/coreclr/jit/namedintrinsiclist.h
src/coreclr/jit/namedintrinsiclist.h
+1
-0
src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
+174
-158
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
+7
-0
src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
...r/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
+1
-0
src/coreclr/tools/Common/TypeSystem/IL/Stubs/ComparerIntrinsics.cs
...lr/tools/Common/TypeSystem/IL/Stubs/ComparerIntrinsics.cs
+8
-0
src/coreclr/tools/aot/jitinterface/jitinterface.h
src/coreclr/tools/aot/jitinterface/jitinterface.h
+10
-0
src/coreclr/vm/corelib.h
src/coreclr/vm/corelib.h
+7
-0
src/coreclr/vm/jitinterface.cpp
src/coreclr/vm/jitinterface.cpp
+97
-1
src/coreclr/vm/jitinterface.h
src/coreclr/vm/jitinterface.h
+4
-0
src/coreclr/zap/zapinfo.cpp
src/coreclr/zap/zapinfo.cpp
+6
-0
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs
...rivate.CoreLib/src/System/Collections/Generic/Comparer.cs
+1
-0
src/tests/JIT/opt/Devirtualization/Comparer_get_Default.cs
src/tests/JIT/opt/Devirtualization/Comparer_get_Default.cs
+244
-0
src/tests/JIT/opt/Devirtualization/Comparer_get_Default.csproj
...ests/JIT/opt/Devirtualization/Comparer_get_Default.csproj
+9
-0
src/tests/issues.targets
src/tests/issues.targets
+3
-0
未找到文件。
src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs
浏览文件 @
a08fec66
...
...
@@ -10,7 +10,7 @@ public abstract partial class Comparer<T> : IComparer, IComparer<T>
{
// To minimize generic instantiation overhead of creating the comparer per type, we keep the generic portion of the code as small
// as possible and define most of the creation logic in a non-generic class.
public
static
Comparer
<
T
>
Default
{
get
;
}
=
(
Comparer
<
T
>)
ComparerHelpers
.
CreateDefaultComparer
(
typeof
(
T
));
public
static
Comparer
<
T
>
Default
{
[
Intrinsic
]
get
;
}
=
(
Comparer
<
T
>)
ComparerHelpers
.
CreateDefaultComparer
(
typeof
(
T
));
}
internal
sealed
partial
class
EnumComparer
<
T
>
:
Comparer
<
T
>
where
T
:
struct
,
Enum
...
...
src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h
浏览文件 @
a08fec66
...
...
@@ -74,6 +74,7 @@ LWM(GetClassSize, DWORDLONG, DWORD)
LWM
(
GetHeapClassSize
,
DWORDLONG
,
DWORD
)
LWM
(
CanAllocateOnStack
,
DWORDLONG
,
DWORD
)
LWM
(
GetCookieForPInvokeCalliSig
,
GetCookieForPInvokeCalliSigValue
,
DLDL
)
LWM
(
GetDefaultComparerClass
,
DWORDLONG
,
DWORDLONG
)
LWM
(
GetDefaultEqualityComparerClass
,
DWORDLONG
,
DWORDLONG
)
LWM
(
GetDelegateCtor
,
Agnostic_GetDelegateCtorIn
,
Agnostic_GetDelegateCtorOut
)
LWM
(
GetEEInfo
,
DWORD
,
Agnostic_CORINFO_EE_INFO
)
...
...
src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
浏览文件 @
a08fec66
...
...
@@ -3101,6 +3101,23 @@ CORINFO_METHOD_HANDLE MethodContext::repGetUnboxedEntry(CORINFO_METHOD_HANDLE ft
return
(
CORINFO_METHOD_HANDLE
)(
result
.
A
);
}
void
MethodContext
::
recGetDefaultComparerClass
(
CORINFO_CLASS_HANDLE
cls
,
CORINFO_CLASS_HANDLE
result
)
{
if
(
GetDefaultComparerClass
==
nullptr
)
GetDefaultComparerClass
=
new
LightWeightMap
<
DWORDLONG
,
DWORDLONG
>
();
GetDefaultComparerClass
->
Add
(
CastHandle
(
cls
),
CastHandle
(
result
));
}
void
MethodContext
::
dmpGetDefaultComparerClass
(
DWORDLONG
key
,
DWORDLONG
value
)
{
printf
(
"GetDefaultComparerClass key cls-%016llX, value cls-%016llX"
,
key
,
value
);
}
CORINFO_CLASS_HANDLE
MethodContext
::
repGetDefaultComparerClass
(
CORINFO_CLASS_HANDLE
cls
)
{
CORINFO_CLASS_HANDLE
result
=
(
CORINFO_CLASS_HANDLE
)
GetDefaultComparerClass
->
Get
(
CastHandle
(
cls
));
return
result
;
}
void
MethodContext
::
recGetDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
cls
,
CORINFO_CLASS_HANDLE
result
)
{
if
(
GetDefaultEqualityComparerClass
==
nullptr
)
...
...
src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h
浏览文件 @
a08fec66
...
...
@@ -401,6 +401,10 @@ public:
void
dmpGetUnboxedEntry
(
DWORDLONG
key
,
DLD
value
);
CORINFO_METHOD_HANDLE
repGetUnboxedEntry
(
CORINFO_METHOD_HANDLE
ftn
,
bool
*
requiresInstMethodTableArg
);
void
recGetDefaultComparerClass
(
CORINFO_CLASS_HANDLE
cls
,
CORINFO_CLASS_HANDLE
result
);
void
dmpGetDefaultComparerClass
(
DWORDLONG
key
,
DWORDLONG
value
);
CORINFO_CLASS_HANDLE
repGetDefaultComparerClass
(
CORINFO_CLASS_HANDLE
cls
);
void
recGetDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
cls
,
CORINFO_CLASS_HANDLE
result
);
void
dmpGetDefaultEqualityComparerClass
(
DWORDLONG
key
,
DWORDLONG
value
);
CORINFO_CLASS_HANDLE
repGetDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
cls
);
...
...
@@ -867,7 +871,7 @@ private:
};
// ********************* Please keep this up-to-date to ease adding more ***************
// Highest packet number: 18
7
// Highest packet number: 18
8
// *************************************************************************************
enum
mcPackets
{
...
...
@@ -943,6 +947,7 @@ enum mcPackets
Packet_GetIntConfigValue
=
151
,
// Added 2/12/2015
Packet_GetStringConfigValue
=
152
,
// Added 2/12/2015
Packet_GetCookieForPInvokeCalliSig
=
48
,
Packet_GetDefaultComparerClass
=
188
,
// Added 2/10/2021
Packet_GetDefaultEqualityComparerClass
=
162
,
// Added 9/24/2017
Packet_GetDelegateCtor
=
49
,
Packet_GetEEInfo
=
50
,
...
...
src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
浏览文件 @
a08fec66
...
...
@@ -252,6 +252,16 @@ CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ft
return
result
;
}
// Given T, return the type of the default Comparer<T>.
// Returns null if the type can't be determined exactly.
CORINFO_CLASS_HANDLE
interceptor_ICJI
::
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
cls
)
{
mc
->
cr
->
AddCall
(
"getDefaultComparerClass"
);
CORINFO_CLASS_HANDLE
result
=
original_ICorJitInfo
->
getDefaultComparerClass
(
cls
);
mc
->
recGetDefaultComparerClass
(
cls
,
result
);
return
result
;
}
// Given T, return the type of the default EqualityComparer<T>.
// Returns null if the type can't be determined exactly.
CORINFO_CLASS_HANDLE
interceptor_ICJI
::
getDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
cls
)
...
...
src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
浏览文件 @
a08fec66
...
...
@@ -132,6 +132,13 @@ CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry(
return
original_ICorJitInfo
->
getUnboxedEntry
(
ftn
,
requiresInstMethodTableArg
);
}
CORINFO_CLASS_HANDLE
interceptor_ICJI
::
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
mcs
->
AddCall
(
"getDefaultComparerClass"
);
return
original_ICorJitInfo
->
getDefaultComparerClass
(
elemType
);
}
CORINFO_CLASS_HANDLE
interceptor_ICJI
::
getDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
...
...
src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
浏览文件 @
a08fec66
...
...
@@ -118,6 +118,12 @@ CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry(
return
original_ICorJitInfo
->
getUnboxedEntry
(
ftn
,
requiresInstMethodTableArg
);
}
CORINFO_CLASS_HANDLE
interceptor_ICJI
::
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
return
original_ICorJitInfo
->
getDefaultComparerClass
(
elemType
);
}
CORINFO_CLASS_HANDLE
interceptor_ICJI
::
getDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
...
...
src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp
浏览文件 @
a08fec66
...
...
@@ -186,6 +186,15 @@ CORINFO_METHOD_HANDLE MyICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* r
return
result
;
}
// Given T, return the type of the default Comparer<T>.
// Returns null if the type can't be determined exactly.
CORINFO_CLASS_HANDLE
MyICJI
::
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
cls
)
{
jitInstance
->
mc
->
cr
->
AddCall
(
"getDefaultComparerClass"
);
CORINFO_CLASS_HANDLE
result
=
jitInstance
->
mc
->
repGetDefaultComparerClass
(
cls
);
return
result
;
}
// Given T, return the type of the default EqualityComparer<T>.
// Returns null if the type can't be determined exactly.
CORINFO_CLASS_HANDLE
MyICJI
::
getDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
cls
)
...
...
src/coreclr/inc/corinfo.h
浏览文件 @
a08fec66
...
...
@@ -2057,6 +2057,12 @@ public:
bool
*
requiresInstMethodTableArg
)
=
0
;
// Given T, return the type of the default Comparer<T>.
// Returns null if the type can't be determined exactly.
virtual
CORINFO_CLASS_HANDLE
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
=
0
;
// Given T, return the type of the default EqualityComparer<T>.
// Returns null if the type can't be determined exactly.
virtual
CORINFO_CLASS_HANDLE
getDefaultEqualityComparerClass
(
...
...
src/coreclr/inc/icorjitinfoimpl_generated.h
浏览文件 @
a08fec66
...
...
@@ -85,6 +85,9 @@ CORINFO_METHOD_HANDLE getUnboxedEntry(
CORINFO_METHOD_HANDLE
ftn
,
bool
*
requiresInstMethodTableArg
)
override
;
CORINFO_CLASS_HANDLE
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
override
;
CORINFO_CLASS_HANDLE
getDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
override
;
...
...
src/coreclr/inc/jiteeversionguid.h
浏览文件 @
a08fec66
...
...
@@ -32,11 +32,11 @@
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
constexpr
GUID
JITEEVersionIdentifier
=
{
/*
20017875-6552-4375-80A8-F7E2CFC6AAB7
*/
0x
20017875
,
0x
6552
,
0x4
375
,
{
0x
80
,
0xa8
,
0xf7
,
0xe2
,
0xcf
,
0xc6
,
0xaa
,
0xb7
}
constexpr
GUID
JITEEVersionIdentifier
=
{
/*
6ca59d19-13a4-44f7-a184-e9cd1e8f57f8
*/
0x
6ca59d19
,
0x
13a4
,
0x4
4f7
,
{
0x
a1
,
0x84
,
0xe9
,
0xcd
,
0x1e
,
0x8f
,
0x57
,
0xf8
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
...
...
src/coreclr/jit/ICorJitInfo_API_names.h
浏览文件 @
a08fec66
...
...
@@ -18,6 +18,7 @@ DEF_CLR_API(getMethodModule)
DEF_CLR_API
(
getMethodVTableOffset
)
DEF_CLR_API
(
resolveVirtualMethod
)
DEF_CLR_API
(
getUnboxedEntry
)
DEF_CLR_API
(
getDefaultComparerClass
)
DEF_CLR_API
(
getDefaultEqualityComparerClass
)
DEF_CLR_API
(
expandRawHandleIntrinsic
)
DEF_CLR_API
(
getIntrinsicID
)
...
...
src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
浏览文件 @
a08fec66
...
...
@@ -154,6 +154,15 @@ CORINFO_METHOD_HANDLE WrapICorJitInfo::getUnboxedEntry(
return
temp
;
}
CORINFO_CLASS_HANDLE
WrapICorJitInfo
::
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
API_ENTER
(
getDefaultComparerClass
);
CORINFO_CLASS_HANDLE
temp
=
wrapHnd
->
getDefaultComparerClass
(
elemType
);
API_LEAVE
(
getDefaultComparerClass
);
return
temp
;
}
CORINFO_CLASS_HANDLE
WrapICorJitInfo
::
getDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
...
...
src/coreclr/jit/flowgraph.cpp
浏览文件 @
a08fec66
...
...
@@ -926,13 +926,14 @@ GenTreeCall* Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfo
GenTreeCall
*
result
=
gtNewHelperCallNode
(
helper
,
type
,
argList
);
result
->
gtFlags
|=
callFlags
;
// If we're importing the special EqualityComparer<T>.Default
// intrinsic, flag the helper call. Later during inlining, we can
// If we're importing the special EqualityComparer<T>.Default
or Comparer<T>.Default
// intrinsic
s
, flag the helper call. Later during inlining, we can
// remove the helper call if the associated field lookup is unused.
if
((
info
.
compFlags
&
CORINFO_FLG_JIT_INTRINSIC
)
!=
0
)
{
NamedIntrinsic
ni
=
lookupNamedIntrinsic
(
info
.
compMethodHnd
);
if
(
ni
==
NI_System_Collections_Generic_EqualityComparer_get_Default
)
if
((
ni
==
NI_System_Collections_Generic_EqualityComparer_get_Default
)
||
(
ni
==
NI_System_Collections_Generic_Comparer_get_Default
))
{
JITDUMP
(
"
\n
marking helper call [%06u] as special dce...
\n
"
,
result
->
gtTreeID
);
result
->
gtCallMoreFlags
|=
GTF_CALL_M_HELPER_SPECIAL_DCE
;
...
...
src/coreclr/jit/importer.cpp
浏览文件 @
a08fec66
...
...
@@ -4458,6 +4458,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
break;
}
case NI_System_Collections_Generic_Comparer_get_Default:
case NI_System_Collections_Generic_EqualityComparer_get_Default:
{
// Flag for later handling during devirtualization.
...
...
@@ -4943,6 +4944,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
{
result = NI_System_Collections_Generic_EqualityComparer_get_Default;
}
else if ((strcmp(className, "Comparer`1") == 0) && (strcmp(methodName, "get_Default") == 0))
{
result = NI_System_Collections_Generic_Comparer_get_Default;
}
}
else if ((strcmp(namespaceName, "System.Numerics") == 0) && (strcmp(className, "BitOperations") == 0))
{
...
...
@@ -21475,6 +21480,7 @@ CORINFO_CLASS_HANDLE Compiler::impGetSpecialIntrinsicExactReturnType(CORINFO_MET
const NamedIntrinsic ni = lookupNamedIntrinsic(methodHnd);
switch (ni)
{
case NI_System_Collections_Generic_Comparer_get_Default:
case NI_System_Collections_Generic_EqualityComparer_get_Default:
{
// Expect one class generic parameter; figure out which it is.
...
...
@@ -21496,7 +21502,15 @@ CORINFO_CLASS_HANDLE Compiler::impGetSpecialIntrinsicExactReturnType(CORINFO_MET
if (isFinalType)
{
result = info.compCompHnd->getDefaultEqualityComparerClass(typeHnd);
if (ni == NI_System_Collections_Generic_EqualityComparer_get_Default)
{
result = info.compCompHnd->getDefaultEqualityComparerClass(typeHnd);
}
else
{
assert(ni == NI_System_Collections_Generic_Comparer_get_Default);
result = info.compCompHnd->getDefaultComparerClass(typeHnd);
}
JITDUMP("Special intrinsic for type %s: return type is %s\n", eeGetClassName(typeHnd),
result != nullptr ? eeGetClassName(result) : "unknown");
}
...
...
src/coreclr/jit/namedintrinsiclist.h
浏览文件 @
a08fec66
...
...
@@ -42,6 +42,7 @@ enum NamedIntrinsic : unsigned short
NI_System_Math_Tanh
,
NI_SYSTEM_MATH_END
,
NI_System_Collections_Generic_Comparer_get_Default
,
NI_System_Collections_Generic_EqualityComparer_get_Default
,
NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness
,
NI_System_Numerics_BitOperations_PopCount
,
...
...
src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
浏览文件 @
a08fec66
此差异已折叠。
点击以展开。
src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
浏览文件 @
a08fec66
...
...
@@ -1056,6 +1056,13 @@ private bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info)
return
result
!=
null
?
ObjectToHandle
(
result
)
:
null
;
}
private
CORINFO_CLASS_STRUCT_
*
getDefaultComparerClass
(
CORINFO_CLASS_STRUCT_
*
elemType
)
{
TypeDesc
comparand
=
HandleToObject
(
elemType
);
TypeDesc
comparer
=
IL
.
Stubs
.
ComparerIntrinsics
.
GetComparerForType
(
comparand
);
return
comparer
!=
null
?
ObjectToHandle
(
comparer
)
:
null
;
}
private
CORINFO_CLASS_STRUCT_
*
getDefaultEqualityComparerClass
(
CORINFO_CLASS_STRUCT_
*
elemType
)
{
TypeDesc
comparand
=
HandleToObject
(
elemType
);
...
...
src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
浏览文件 @
a08fec66
...
...
@@ -175,6 +175,7 @@ FUNCTIONS
void getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, unsigned* offsetAfterIndirection, bool* isRelative);
bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info);
CORINFO_METHOD_HANDLE getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg);
CORINFO_CLASS_HANDLE getDefaultComparerClass(CORINFO_CLASS_HANDLE elemType);
CORINFO_CLASS_HANDLE getDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE elemType);
void expandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_GENERICHANDLE_RESULT * pResult);
CorInfoIntrinsics getIntrinsicID( CORINFO_METHOD_HANDLE method , BoolStar pMustExpand);
...
...
src/coreclr/tools/Common/TypeSystem/IL/Stubs/ComparerIntrinsics.cs
浏览文件 @
a08fec66
...
...
@@ -31,6 +31,14 @@ public static MethodIL EmitEqualityComparerCreate(MethodDesc target)
return
EmitComparerAndEqualityComparerCreateCommon
(
target
,
"EqualityComparer"
,
"IEquatable`1"
);
}
/// <summary>
/// Gets the concrete type Comparer`1.Create returns or null if it's not known at compile time.
/// </summary>
public
static
TypeDesc
GetComparerForType
(
TypeDesc
comparand
)
{
return
GetComparerForType
(
comparand
,
"Comparer"
,
"IComparable`1"
);
}
/// <summary>
/// Gets the concrete type EqualityComparer`1.Create returns or null if it's not known at compile time.
/// </summary>
...
...
src/coreclr/tools/aot/jitinterface/jitinterface.h
浏览文件 @
a08fec66
...
...
@@ -24,6 +24,7 @@ struct JitInterfaceCallbacks
void
(
*
getMethodVTableOffset
)(
void
*
thisHandle
,
CorInfoExceptionClass
**
ppException
,
void
*
method
,
unsigned
*
offsetOfIndirection
,
unsigned
*
offsetAfterIndirection
,
bool
*
isRelative
);
bool
(
*
resolveVirtualMethod
)(
void
*
thisHandle
,
CorInfoExceptionClass
**
ppException
,
void
*
info
);
void
*
(
*
getUnboxedEntry
)(
void
*
thisHandle
,
CorInfoExceptionClass
**
ppException
,
void
*
ftn
,
bool
*
requiresInstMethodTableArg
);
void
*
(
*
getDefaultComparerClass
)(
void
*
thisHandle
,
CorInfoExceptionClass
**
ppException
,
void
*
elemType
);
void
*
(
*
getDefaultEqualityComparerClass
)(
void
*
thisHandle
,
CorInfoExceptionClass
**
ppException
,
void
*
elemType
);
void
(
*
expandRawHandleIntrinsic
)(
void
*
thisHandle
,
CorInfoExceptionClass
**
ppException
,
void
*
pResolvedToken
,
void
*
pResult
);
int
(
*
getIntrinsicID
)(
void
*
thisHandle
,
CorInfoExceptionClass
**
ppException
,
void
*
method
,
bool
*
pMustExpand
);
...
...
@@ -338,6 +339,15 @@ public:
return
temp
;
}
virtual
void
*
getDefaultComparerClass
(
void
*
elemType
)
{
CorInfoExceptionClass
*
pException
=
nullptr
;
void
*
temp
=
_callbacks
->
getDefaultComparerClass
(
_thisHandle
,
&
pException
,
elemType
);
if
(
pException
!=
nullptr
)
throw
pException
;
return
temp
;
}
virtual
void
*
getDefaultEqualityComparerClass
(
void
*
elemType
)
{
...
...
src/coreclr/vm/corelib.h
浏览文件 @
a08fec66
...
...
@@ -1189,6 +1189,13 @@ DEFINE_CLASS(NULLABLE_EQUALITYCOMPARER, CollectionsGeneric, NullableEqualityComp
DEFINE_CLASS
(
GENERIC_EQUALITYCOMPARER
,
CollectionsGeneric
,
GenericEqualityComparer
`
1
)
DEFINE_CLASS
(
OBJECT_EQUALITYCOMPARER
,
CollectionsGeneric
,
ObjectEqualityComparer
`
1
)
// Classes referenced in Comparer<T>.Default optimization
DEFINE_CLASS
(
GENERIC_COMPARER
,
CollectionsGeneric
,
GenericComparer
`
1
)
DEFINE_CLASS
(
OBJECT_COMPARER
,
CollectionsGeneric
,
ObjectComparer
`
1
)
DEFINE_CLASS
(
ENUM_COMPARER
,
CollectionsGeneric
,
EnumComparer
`
1
)
DEFINE_CLASS
(
NULLABLE_COMPARER
,
CollectionsGeneric
,
NullableComparer
`
1
)
DEFINE_CLASS
(
INATTRIBUTE
,
Interop
,
InAttribute
)
DEFINE_CLASS_U
(
CompilerServices
,
GCHeapHash
,
GCHeapHashObject
)
...
...
src/coreclr/vm/jitinterface.cpp
浏览文件 @
a08fec66
...
...
@@ -9082,6 +9082,99 @@ void CEEInfo::expandRawHandleIntrinsic(
UNREACHABLE
();
// only called with CoreRT.
}
/*********************************************************************/
CORINFO_CLASS_HANDLE
CEEInfo
::
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
CONTRACTL
{
THROWS
;
GC_TRIGGERS
;
MODE_PREEMPTIVE
;
}
CONTRACTL_END
;
CORINFO_CLASS_HANDLE
result
=
NULL
;
JIT_TO_EE_TRANSITION
();
result
=
getDefaultComparerClassHelper
(
elemType
);
EE_TO_JIT_TRANSITION
();
return
result
;
}
CORINFO_CLASS_HANDLE
CEEInfo
::
getDefaultComparerClassHelper
(
CORINFO_CLASS_HANDLE
elemType
)
{
CONTRACTL
{
THROWS
;
GC_TRIGGERS
;
MODE_PREEMPTIVE
;
}
CONTRACTL_END
;
TypeHandle
elemTypeHnd
(
elemType
);
// Mirrors the logic in BCL's CompareHelpers.CreateDefaultComparer
// And in compile.cpp's SpecializeComparer
//
// We need to find the appropriate instantiation
Instantiation
inst
(
&
elemTypeHnd
,
1
);
// If T implements IComparable<T>
if
(
elemTypeHnd
.
CanCastTo
(
TypeHandle
(
CoreLibBinder
::
GetClass
(
CLASS__ICOMPARABLEGENERIC
)).
Instantiate
(
inst
)))
{
TypeHandle
resultTh
=
((
TypeHandle
)
CoreLibBinder
::
GetClass
(
CLASS__GENERIC_COMPARER
)).
Instantiate
(
inst
);
return
CORINFO_CLASS_HANDLE
(
resultTh
.
GetMethodTable
());
}
// Nullable<T>
if
(
Nullable
::
IsNullableType
(
elemTypeHnd
))
{
Instantiation
nullableInst
=
elemTypeHnd
.
AsMethodTable
()
->
GetInstantiation
();
TypeHandle
iequatable
=
TypeHandle
(
CoreLibBinder
::
GetClass
(
CLASS__IEQUATABLEGENERIC
)).
Instantiate
(
nullableInst
);
if
(
nullableInst
[
0
].
CanCastTo
(
iequatable
))
{
TypeHandle
resultTh
=
((
TypeHandle
)
CoreLibBinder
::
GetClass
(
CLASS__NULLABLE_COMPARER
)).
Instantiate
(
nullableInst
);
return
CORINFO_CLASS_HANDLE
(
resultTh
.
GetMethodTable
());
}
}
// We need to special case the Enum comparers based on their underlying type to avoid boxing
if
(
elemTypeHnd
.
IsEnum
())
{
MethodTable
*
targetClass
=
NULL
;
CorElementType
normType
=
elemTypeHnd
.
GetVerifierCorElementType
();
switch
(
normType
)
{
case
ELEMENT_TYPE_I1
:
case
ELEMENT_TYPE_I2
:
case
ELEMENT_TYPE_U1
:
case
ELEMENT_TYPE_U2
:
case
ELEMENT_TYPE_I4
:
case
ELEMENT_TYPE_U4
:
case
ELEMENT_TYPE_I8
:
case
ELEMENT_TYPE_U8
:
{
targetClass
=
CoreLibBinder
::
GetClass
(
CLASS__ENUM_COMPARER
);
break
;
}
default:
break
;
}
if
(
targetClass
!=
NULL
)
{
TypeHandle
resultTh
=
((
TypeHandle
)
targetClass
->
GetCanonicalMethodTable
()).
Instantiate
(
inst
);
return
CORINFO_CLASS_HANDLE
(
resultTh
.
GetMethodTable
());
}
}
// Default case
TypeHandle
resultTh
=
((
TypeHandle
)
CoreLibBinder
::
GetClass
(
CLASS__OBJECT_COMPARER
)).
Instantiate
(
inst
);
return
CORINFO_CLASS_HANDLE
(
resultTh
.
GetMethodTable
());
}
/*********************************************************************/
CORINFO_CLASS_HANDLE
CEEInfo
::
getDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
...
...
@@ -9120,7 +9213,10 @@ CORINFO_CLASS_HANDLE CEEInfo::getDefaultEqualityComparerClassHelper(CORINFO_CLAS
return
CORINFO_CLASS_HANDLE
(
CoreLibBinder
::
GetClass
(
CLASS__BYTE_EQUALITYCOMPARER
));
}
// Else we'll need to find the appropriate instantation
// Mirrors the logic in BCL's CompareHelpers.CreateDefaultComparer
// And in compile.cpp's SpecializeComparer
//
// We need to find the appropriate instantiation
Instantiation
inst
(
&
elemTypeHnd
,
1
);
// If T implements IEquatable<T>
...
...
src/coreclr/vm/jitinterface.h
浏览文件 @
a08fec66
...
...
@@ -452,6 +452,10 @@ public:
bool
resolveVirtualMethodHelper
(
CORINFO_DEVIRTUALIZATION_INFO
*
info
);
CORINFO_CLASS_HANDLE
getDefaultComparerClassHelper
(
CORINFO_CLASS_HANDLE
elemType
);
CORINFO_CLASS_HANDLE
getDefaultEqualityComparerClassHelper
(
CORINFO_CLASS_HANDLE
elemType
);
...
...
src/coreclr/zap/zapinfo.cpp
浏览文件 @
a08fec66
...
...
@@ -4069,6 +4069,12 @@ CORINFO_METHOD_HANDLE ZapInfo::getUnboxedEntry(
return
m_pEEJitInfo
->
getUnboxedEntry
(
ftn
,
requiresInstMethodTableArg
);
}
CORINFO_CLASS_HANDLE
ZapInfo
::
getDefaultComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
return
m_pEEJitInfo
->
getDefaultComparerClass
(
elemType
);
}
CORINFO_CLASS_HANDLE
ZapInfo
::
getDefaultEqualityComparerClass
(
CORINFO_CLASS_HANDLE
elemType
)
{
...
...
src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs
浏览文件 @
a08fec66
...
...
@@ -55,6 +55,7 @@ public ComparisonComparer(Comparison<T> comparison)
// Needs to be public to support binary serialization compatibility
public
sealed
partial
class
GenericComparer
<
T
>
:
Comparer
<
T
>
where
T
:
IComparable
<
T
>
{
[
MethodImpl
(
MethodImplOptions
.
AggressiveInlining
)]
public
override
int
Compare
(
T
?
x
,
T
?
y
)
{
if
(
x
!=
null
)
...
...
src/tests/JIT/opt/Devirtualization/Comparer_get_Default.cs
0 → 100644
浏览文件 @
a08fec66
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using
System
;
using
System.Collections
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Runtime.CompilerServices
;
class
Program
{
private
static
int
s_ReturnCode
=
100
;
private
static
void
AssertEquals
<
T
>(
T
expected
,
T
actual
,
[
CallerLineNumber
]
int
line
=
0
)
{
if
(!
expected
.
Equals
(
actual
))
{
Console
.
WriteLine
(
$"
{
expected
}
!=
{
actual
}
, L
{
line
}
"
);
s_ReturnCode
++;
}
}
private
static
void
Compare_Boolean
(
Boolean
a
,
Boolean
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
Boolean
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Byte
(
Byte
a
,
Byte
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
Byte
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_SByte
(
SByte
a
,
SByte
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
SByte
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Char
(
Char
a
,
Char
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
Char
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_UInt16
(
UInt16
a
,
UInt16
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
UInt16
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Int16
(
Int16
a
,
Int16
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
Int16
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_UInt32
(
UInt32
a
,
UInt32
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
UInt32
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Int32
(
Int32
a
,
Int32
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
Int32
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Int64
(
Int64
a
,
Int64
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
Int64
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_UInt64
(
UInt64
a
,
UInt64
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
UInt64
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_IntPtr
(
IntPtr
a
,
IntPtr
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
IntPtr
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_UIntPtr
(
UIntPtr
a
,
UIntPtr
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
UIntPtr
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_nint
(
nint
a
,
nint
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
nint
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_nuint
(
nuint
a
,
nuint
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
nuint
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Enum_Int32
(
MethodImplOptions
a
,
MethodImplOptions
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
MethodImplOptions
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Enum_Byte
(
Enum_byte
a
,
Enum_byte
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
Enum_byte
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_String
(
String
a
,
String
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
String
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_DateTime
(
DateTime
a
,
DateTime
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
DateTime
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Struct1
(
Struct1
a
,
Struct1
b
)
=>
AssertEquals
(
a
.
CompareTo
(
b
),
Comparer
<
Struct1
>.
Default
.
Compare
(
a
,
b
));
private
static
void
Compare_Int32_Nullable
(
long
?
a
,
long
?
b
)
{
int
actual
=
Comparer
<
long
?>.
Default
.
Compare
(
a
,
b
);
int
expected
=
0
;
if
(
a
.
HasValue
)
expected
=
b
.
HasValue
?
a
.
Value
.
CompareTo
(
b
.
Value
)
:
1
;
else
expected
=
b
.
HasValue
?
-
1
:
0
;
AssertEquals
(
expected
,
actual
);
}
public
static
int
Main
(
string
[]
args
)
{
long
[]
values
=
Enumerable
.
Range
(
1000
,
2000
)
.
Select
(
i
=>
(
long
)
i
)
.
Concat
(
new
[]
{
short
.
MinValue
,
short
.
MinValue
+
1
,
short
.
MaxValue
-
1
,
short
.
MaxValue
,
short
.
MaxValue
+
1
,
int
.
MinValue
,
int
.
MinValue
+
1
,
int
.
MaxValue
,
int
.
MaxValue
-
1
,
long
.
MinValue
,
long
.
MinValue
+
1
,
long
.
MaxValue
,
long
.
MaxValue
-
1
,
})
.
ToArray
();
for
(
var
i
=
0
;
i
<
values
.
Length
;
i
++)
{
for
(
int
j
=
0
;
j
<
values
.
Length
;
j
++)
{
long
a
=
values
[
i
];
long
b
=
values
[
j
];
var
boolA
=
Unsafe
.
As
<
long
,
bool
>(
ref
a
);
var
boolB
=
Unsafe
.
As
<
long
,
bool
>(
ref
b
);
Compare_Boolean
(
boolA
,
boolB
);
var
byteA
=
Unsafe
.
As
<
long
,
byte
>(
ref
a
);
var
byteB
=
Unsafe
.
As
<
long
,
byte
>(
ref
b
);
Compare_Byte
(
byteA
,
byteB
);
var
sbyteA
=
Unsafe
.
As
<
long
,
sbyte
>(
ref
a
);
var
sbyteB
=
Unsafe
.
As
<
long
,
sbyte
>(
ref
b
);
Compare_SByte
(
sbyteA
,
sbyteB
);
var
shortA
=
Unsafe
.
As
<
long
,
short
>(
ref
a
);
var
shortB
=
Unsafe
.
As
<
long
,
short
>(
ref
b
);
Compare_Int16
(
shortA
,
shortB
);
var
ushortA
=
Unsafe
.
As
<
long
,
ushort
>(
ref
a
);
var
ushortB
=
Unsafe
.
As
<
long
,
ushort
>(
ref
b
);
Compare_UInt16
(
ushortA
,
ushortB
);
var
charA
=
Unsafe
.
As
<
long
,
char
>(
ref
a
);
var
charB
=
Unsafe
.
As
<
long
,
char
>(
ref
b
);
Compare_Char
(
charA
,
charB
);
var
intA
=
Unsafe
.
As
<
long
,
int
>(
ref
a
);
var
intB
=
Unsafe
.
As
<
long
,
int
>(
ref
b
);
Compare_Int32
(
intA
,
intB
);
var
uintA
=
Unsafe
.
As
<
long
,
uint
>(
ref
a
);
var
uintB
=
Unsafe
.
As
<
long
,
uint
>(
ref
b
);
Compare_UInt32
(
uintA
,
uintB
);
var
longA
=
Unsafe
.
As
<
long
,
long
>(
ref
a
);
var
longB
=
Unsafe
.
As
<
long
,
long
>(
ref
b
);
Compare_Int64
(
longA
,
longB
);
var
ulongA
=
Unsafe
.
As
<
long
,
ulong
>(
ref
a
);
var
ulongB
=
Unsafe
.
As
<
long
,
ulong
>(
ref
b
);
Compare_UInt64
(
ulongA
,
ulongB
);
var
intPtrA
=
Unsafe
.
As
<
long
,
IntPtr
>(
ref
a
);
var
intPtrB
=
Unsafe
.
As
<
long
,
IntPtr
>(
ref
b
);
Compare_IntPtr
(
intPtrA
,
intPtrB
);
var
uintPtrA
=
Unsafe
.
As
<
long
,
UIntPtr
>(
ref
a
);
var
uintPtrB
=
Unsafe
.
As
<
long
,
UIntPtr
>(
ref
b
);
Compare_UIntPtr
(
uintPtrA
,
uintPtrB
);
var
nintA
=
Unsafe
.
As
<
long
,
nint
>(
ref
a
);
var
nintB
=
Unsafe
.
As
<
long
,
nint
>(
ref
b
);
Compare_nint
(
nintA
,
nintB
);
var
nuintA
=
Unsafe
.
As
<
long
,
nuint
>(
ref
a
);
var
nuintB
=
Unsafe
.
As
<
long
,
nuint
>(
ref
b
);
Compare_nuint
(
nuintA
,
nuintB
);
var
enumIntA
=
Unsafe
.
As
<
long
,
MethodImplOptions
>(
ref
a
);
var
enumIntB
=
Unsafe
.
As
<
long
,
MethodImplOptions
>(
ref
b
);
Compare_Enum_Int32
(
enumIntA
,
enumIntB
);
var
enumByteA
=
Unsafe
.
As
<
long
,
Enum_byte
>(
ref
a
);
var
enumByteB
=
Unsafe
.
As
<
long
,
Enum_byte
>(
ref
b
);
Compare_Enum_Byte
(
enumByteA
,
enumByteB
);
var
structA
=
new
Struct1
{
a
=
a
,
b
=
b
};
var
structB
=
new
Struct1
{
a
=
b
,
b
=
a
};
Compare_Struct1
(
structA
,
structB
);
Compare_DateTime
(
new
DateTime
(
Math
.
Clamp
(
a
,
DateTime
.
MinValue
.
Ticks
,
DateTime
.
MaxValue
.
Ticks
)),
new
DateTime
(
Math
.
Clamp
(
b
,
DateTime
.
MinValue
.
Ticks
,
DateTime
.
MaxValue
.
Ticks
)));
Compare_Int32_Nullable
(
a
,
b
);
}
}
string
[]
strings
=
{
""
,
"0"
,
"00"
,
"1"
,
"11"
,
"111"
,
"привет"
,
"Hello"
};
foreach
(
var
str1
in
strings
)
{
foreach
(
var
str2
in
strings
)
{
Compare_String
(
str1
,
str2
);
Compare_String
(
str2
,
str1
);
}
}
Compare_Int32_Nullable
(
null
,
0
);
Compare_Int32_Nullable
(
0
,
null
);
Compare_Int32_Nullable
(
null
,
null
);
Compare_Int32_Nullable
(
null
,
1
);
Compare_Int32_Nullable
(
1
,
null
);
Compare_Int32_Nullable
(
null
,
-
1
);
Compare_Int32_Nullable
(-
1
,
null
);
GetTypeTests
();
GetHashCodeTests
();
return
s_ReturnCode
;
}
private
static
void
GetTypeTests
()
{
AssertEquals
(
"System.Collections.Generic.GenericComparer`1[System.Int32]"
,
Comparer
<
int
>.
Default
.
GetType
().
ToString
());
AssertEquals
(
"System.Collections.Generic.GenericComparer`1[System.String]"
,
Comparer
<
string
>.
Default
.
GetType
().
ToString
());
AssertEquals
(
"System.Collections.Generic.GenericComparer`1[System.Guid]"
,
Comparer
<
Guid
>.
Default
.
GetType
().
ToString
());
AssertEquals
(
"System.Collections.Generic.EnumComparer`1[System.Runtime.CompilerServices.MethodImplOptions]"
,
Comparer
<
MethodImplOptions
>.
Default
.
GetType
().
ToString
());
AssertEquals
(
"System.Collections.Generic.NullableComparer`1[System.Byte]"
,
Comparer
<
byte
?>.
Default
.
GetType
().
ToString
());
AssertEquals
(
"System.Collections.Generic.ObjectComparer`1[Struct1]"
,
Comparer
<
Struct1
>.
Default
.
GetType
().
ToString
());
}
private
static
int
GetHashCodeTests
()
{
// Just to make sure it doesn't crash
return
Comparer
<
int
>.
Default
.
GetHashCode
()
+
Comparer
<
string
>.
Default
.
GetHashCode
()
+
Comparer
<
MethodImplOptions
>.
Default
.
GetHashCode
()
+
Comparer
<
byte
?>.
Default
.
GetHashCode
()
+
Comparer
<
Guid
>.
Default
.
GetHashCode
()
+
Comparer
<
Struct1
>.
Default
.
GetHashCode
();
}
}
public
enum
Enum_byte
:
byte
{
A
,
B
,
C
,
D
,
E
}
public
struct
Struct1
:
IComparable
{
public
long
a
;
public
long
b
;
public
int
CompareTo
(
object
?
obj
)
{
return
b
.
CompareTo
(((
Struct1
)
obj
).
b
);
}
}
src/tests/JIT/opt/Devirtualization/Comparer_get_Default.csproj
0 → 100644
浏览文件 @
a08fec66
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="Comparer_get_Default.cs" />
</ItemGroup>
</Project>
src/tests/issues.targets
浏览文件 @
a08fec66
...
...
@@ -963,6 +963,9 @@
<!-- Known failures for mono runtime on *all* architectures/operating systems -->
<ItemGroup
Condition=
"'$(RuntimeFlavor)' == 'mono'"
>
<ExcludeList
Include=
"$(XunitTestBinBase)/JIT/opt/Devirtualization/Comparer_get_Default/*"
>
<Issue>
https://github.com/dotnet/runtime/issues/48190
</Issue>
</ExcludeList>
<ExcludeList
Include=
"$(XunitTestBinBase)/JIT/Directed/DynamicPgo/**"
>
<Issue>
Mono doesn't have a dynamic pgo or tiered compilation infrastructure
</Issue>
</ExcludeList>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录