C#中的[固有]属性做什么?
在谷歌上快速搜索“instrinicattributec#”,只会返回有关其他属性的文章,例如C#中的[固有]属性做什么?,c#,.net,.net-core,intrinsics,C#,.net,.net Core,Intrinsics,在谷歌上快速搜索“instrinicattributec#”,只会返回有关其他属性的文章,例如[Serializable]。显然,这些被称为“内在属性” 然而,C#中还有一个属性,它本身被称为[内在],我正试图弄清楚它到底是什么以及它是如何工作的。它不存在于.NET文档的页面上,也不存在于我所能看到的文档中的任何其他地方 此属性在.NET Core内部的多个位置使用,例如,在文件夹中,例如。代码段: [固有] 公共向量2(浮点x,浮点y) { X=X; Y=Y; } 说明: 使用 Intrins
[Serializable]
。显然,这些被称为“内在属性”
然而,C#中还有一个属性,它本身被称为[内在]
,我正试图弄清楚它到底是什么以及它是如何工作的。它不存在于.NET文档的页面上,也不存在于我所能看到的文档中的任何其他地方
此属性在.NET Core内部的多个位置使用,例如,在文件夹中,例如。代码段:
[固有]
公共向量2(浮点x,浮点y)
{
X=X;
Y=Y;
}
说明:
使用
IntrinsicatAttribute自定义属性。如果使用
属性,编译器不知道
给定类型的实现将在运行时出现。
标记为内在类型的方法可以将方法声明为
extern,在这种情况下,假定实现在
运行时
来源:MSIL到JavaScript编译器,第4.4.1.1节
链接:
一般来说,我建议不要在意它,也不要将它用于您自己的类。以下是我在github上的存储库中进行了非常有限的搜索后找到的内容
[固有]
标记可能被JIT替换/优化的方法、属性和字段。源代码注释说明了类似的内容():
在某些调用站点上,对方法的调用或对标记有此属性的字段的引用可能会被jit内部扩展替换。运行时/编译器可能会特别处理标记有此属性的类型
目的
对于核心开发人员,[固有]
至少有两个用途:
- 它通知开发人员标记的字段、方法或属性的代码可以被VM替换。因此,如果代码发生了变化,那么可能应该在这两个地方引入变化李>
- 它被用作JIT优化器的标志,以快速识别可能被优化的方法
Enum.HasFlag
,而在其他情况下则不能。为此,需要将方法标识为Enum.HasFlag
,检查一些条件并用更优化的实现替换它。优化器可以通过名称识别方法,但是,出于性能原因,最好在执行字符串比较之前通过简单的标志筛选出方法
用法
该属性仅与核心开发人员相关。您应该只在内部类中使用它,并且只在您想要为它提出非常具体的JIT级别优化的情况下使用它<代码>[固有]非常局限于一小部分广泛使用的.Net类,由于某些原因,这些类无法通过其他方法进行优化
从评论中可以看出:我计划为.NETCore提出一个颜色结构,它需要与其他内置类型的行为类似,以保持一致性
您可能不应该在初始提案中使用[固有]
。在它通过之后,您可以考虑优化,如果您有一个有效的场景,Color
将从低级优化中受益,那么您可以建议对它的一些方法或属性使用[固有]
工作原理
以下是当前在core中如何使用[固有]
:
- 它被定义为一个众所周知的属性():
- VM对其进行解析,并将方法()的
标志设置为true:isjit
- 此标志用于在方法属性()中设置另一个标志:
- 此标志稍后用于筛选出明显不是内在()的方法:
然后调用以确定(主要是通过名称)真正(而不仅仅是潜在)应该优化的方法impinfrant
- 在所有这些之后,
可以基于方法执行优化。例如,importer
()的优化:Enum.HasFlag
[内在]
的简短时间线:
- 在2014年之前的某个时候,
属性作为[JitIntrisic]
的目标是支持新的处理器指令(请参阅)系统的一部分引入。数字
- 2016年6月6日,发行。当时,
存在众所周知的性能问题(请参阅)Enum.HasFlag
- 在处理这个问题时,我们建议引入一种通用机制来引入JIT本质()
- 这导致了两个pull请求:介绍了
的一般机制,并为[内在]
实现了它。我建议仔细阅读这两篇文章,因为它们非常能说明Enum.HasFlag
所带来的变化[内在]
- 后来,在关于移动的讨论中,有人建议,
不在任何地方使用,应该替换/删除:[jit]
- 很快,
被删除并替换为[jitInquired]
()。这就是为什么这个属性出现在[Inquired]
中Vector2
case WellKnownAttribute::Intrinsic:
return "System.Runtime.CompilerServices.IntrinsicAttribute";
if (bmtProp->fIsHardwareIntrinsic || (S_OK == GetCustomAttribute(pMethod->GetMethodSignature().GetToken(),
WellKnownAttribute::Intrinsic,
NULL,
NULL)))
{
pNewMD->SetIsJitIntrinsic();
}
if (pMD->IsJitIntrinsic())
result |= CORINFO_FLG_JIT_INTRINSIC;
if ((mflags & (CORINFO_FLG_INTRINSIC | CORINFO_FLG_JIT_INTRINSIC)) != 0)
{
const bool isTail = canTailCall && (tailCall != 0);
call = impIntrinsic(newobjThis, clsHnd, methHnd, sig, mflags, pResolvedToken->token, readonlyCall, isTail,
pConstrainedResolvedToken, callInfo->thisTransform, &intrinsicID, &isSpecialIntrinsic);
case NI_System_Enum_HasFlag:
{
GenTree* thisOp = impStackTop(1).val;
GenTree* flagOp = impStackTop(0).val;
GenTree* optTree = gtOptimizeEnumHasFlag(thisOp, flagOp);
if (optTree != nullptr)
{
// Optimization successful. Pop the stack for real.
impPopStack();
impPopStack();
retNode = optTree;
}
else
{
// Retry optimizing this during morph.
isSpecial = true;
}
break;
}