summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h8
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/lwmlist.h1
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp84
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/methodcontext.h15
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp11
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp9
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp8
-rw-r--r--src/ToolBox/superpmi/superpmi/icorjitinfo.cpp9
-rw-r--r--src/inc/corinfo.h22
-rw-r--r--src/jit/ICorJitInfo_API_names.h1
-rw-r--r--src/jit/ICorJitInfo_API_wrapper.hpp11
-rw-r--r--src/jit/compiler.h1
-rw-r--r--src/jit/importer.cpp38
-rw-r--r--src/mscorlib/shared/System.Private.CoreLib.Shared.projitems1
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs13
-rw-r--r--src/mscorlib/src/System/Enum.cs13
-rw-r--r--src/vm/classnames.h1
-rw-r--r--src/vm/jitinterface.cpp44
-rw-r--r--src/vm/jitinterface.h1
-rw-r--r--src/vm/method.hpp16
-rw-r--r--src/vm/methodtablebuilder.cpp14
-rw-r--r--src/zap/zapinfo.cpp5
-rw-r--r--src/zap/zapinfo.h4
23 files changed, 315 insertions, 15 deletions
diff --git a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h
index ad6b269041..4ce775d177 100644
--- a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h
+++ b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h
@@ -670,6 +670,14 @@ const char* getMethodName(CORINFO_METHOD_HANDLE ftn, /* IN */
const char** moduleName /* OUT */
);
+// Return method name as in metadata, or nullptr if there is none,
+// and optionally return the class name as in metadata.
+// Suitable for non-debugging use.
+const char* getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char** className, /* OUT */
+ const char** namespaceName /* OUT */
+ );
+
// this function is for debugging only. It returns a value that
// is will always be the same for a given method. It is used
// to implement the 'jitRange' functionality
diff --git a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h
index 349b6bf105..898641c790 100644
--- a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h
+++ b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h
@@ -100,6 +100,7 @@ LWM(GetMethodDefFromMethod, DWORDLONG, DWORD)
LWM(GetMethodHash, DWORDLONG, DWORD)
LWM(GetMethodInfo, DWORDLONG, Agnostic_GetMethodInfo)
LWM(GetMethodName, DLD, DD)
+LWM(GetMethodNameFromMetadata, DLDD, DDD)
LWM(GetMethodSig, DLDL, Agnostic_CORINFO_SIG_INFO)
LWM(GetMethodSync, DWORDLONG, DLDL)
LWM(GetMethodVTableOffset, DWORDLONG, DDD)
diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
index 82a7985ce5..154505632b 100644
--- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
+++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
@@ -1121,6 +1121,7 @@ void MethodContext::dmpGetMethodName(DLD key, DD value)
moduleName);
GetMethodName->Unlock();
}
+
const char* MethodContext::repGetMethodName(CORINFO_METHOD_HANDLE ftn, const char** moduleName)
{
const char* result = "hackishMethodName";
@@ -1148,6 +1149,85 @@ const char* MethodContext::repGetMethodName(CORINFO_METHOD_HANDLE ftn, const cha
return result;
}
+
+void MethodContext::recGetMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn,
+ char* methodName, const char** className, const char **namespaceName)
+{
+ if (GetMethodNameFromMetadata == nullptr)
+ GetMethodNameFromMetadata = new LightWeightMap<DLDD, DDD>();
+ DDD value;
+ DLDD key;
+ key.A = (DWORDLONG)ftn;
+ key.B = (className != nullptr);
+ key.C = (namespaceName != nullptr);
+
+ if (methodName != nullptr)
+ value.A = GetMethodNameFromMetadata->AddBuffer((unsigned char*)methodName, (DWORD)strlen(methodName) + 1);
+ else
+ value.A = (DWORD)-1;
+
+ if (className != nullptr)
+ value.B = GetMethodNameFromMetadata->AddBuffer((unsigned char*)*className, (DWORD)strlen(*className) + 1);
+ else
+ value.B = (DWORD)-1;
+
+ if (namespaceName != nullptr)
+ value.C = GetMethodNameFromMetadata->AddBuffer((unsigned char*)*namespaceName, (DWORD)strlen(*namespaceName) + 1);
+ else
+ value.C = (DWORD)-1;
+
+ GetMethodNameFromMetadata->Add(key, value);
+ DEBUG_REC(dmpGetMethodNameFromMetadata(key, value));
+}
+
+void MethodContext::dmpGetMethodNameFromMetadata(DLDD key, DDD value)
+{
+ unsigned char* methodName = (unsigned char*)GetMethodName->GetBuffer(value.A);
+ unsigned char* className = (unsigned char*)GetMethodName->GetBuffer(value.B);
+ unsigned char* namespaceName = (unsigned char*)GetMethodName->GetBuffer(value.C);
+ printf("GetMethodNameFromMetadata key - ftn-%016llX classNonNull-%u namespaceNonNull-%u, value meth-'%s', class-'%s', namespace-'%s'",
+ key.A, key.B, key.C, methodName, className, namespaceName);
+ GetMethodNameFromMetadata->Unlock();
+}
+
+const char* MethodContext::repGetMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, const char** moduleName, const char** namespaceName)
+{
+ const char* result = nullptr;
+ DDD value;
+ DLDD key;
+ key.A = (DWORDLONG)ftn;
+ key.B = (moduleName != nullptr);
+ key.C = (namespaceName != nullptr);
+
+ int itemIndex = -1;
+ if (GetMethodNameFromMetadata != nullptr)
+ itemIndex = GetMethodNameFromMetadata->GetIndex(key);
+ if (itemIndex < 0)
+ {
+ if (moduleName != nullptr)
+ {
+ *moduleName = nullptr;
+ }
+ }
+ else
+ {
+ value = GetMethodNameFromMetadata->Get(key);
+ result = (const char*)GetMethodNameFromMetadata->GetBuffer(value.A);
+
+ if (moduleName != nullptr)
+ {
+ *moduleName = (const char*)GetMethodNameFromMetadata->GetBuffer(value.B);
+ }
+
+ if (namespaceName != nullptr)
+ {
+ *namespaceName = (const char*)GetMethodNameFromMetadata->GetBuffer(value.C);
+ }
+ }
+ DEBUG_REP(dmpGetMethodNameFromMetadata(key, value));
+ return result;
+}
+
void MethodContext::recGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes, DWORD result)
{
if (GetJitFlags == nullptr)
@@ -2980,7 +3060,7 @@ void MethodContext::recGetMethodVTableOffset(CORINFO_METHOD_HANDLE method,
DDD value;
value.A = (DWORD)*offsetOfIndirection;
value.B = (DWORD)*offsetAfterIndirection;
- value.C = *isRelative;
+ value.C = *isRelative ? 1 : 0;
GetMethodVTableOffset->Add((DWORDLONG)method, value);
DEBUG_REC(dmpGetMethodVTableOffset((DWORDLONG)method, value));
}
@@ -3003,7 +3083,7 @@ void MethodContext::repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method,
*offsetOfIndirection = (unsigned)value.A;
*offsetAfterIndirection = (unsigned)value.B;
- *isRelative = value.C;
+ *isRelative = value.C != 0;
DEBUG_REP(dmpGetMethodVTableOffset((DWORDLONG)method, value));
}
diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
index 83c16772ae..eec403196b 100644
--- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
+++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
@@ -89,6 +89,12 @@ public:
DWORDLONG A;
DWORD B;
};
+ struct DLDD
+ {
+ DWORDLONG A;
+ DWORD B;
+ DWORD C;
+ };
struct Agnostic_CORINFO_RESOLVED_TOKENin
{
DWORDLONG tokenContext;
@@ -241,7 +247,7 @@ public:
{
DWORD A;
DWORD B;
- bool C;
+ DWORD C;
};
struct Agnostic_CanTailCall
{
@@ -616,6 +622,10 @@ public:
void dmpGetMethodName(DLD key, DD value);
const char* repGetMethodName(CORINFO_METHOD_HANDLE ftn, const char** moduleName);
+ void recGetMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, char* methodname, const char** moduleName, const char** namespaceName);
+ void dmpGetMethodNameFromMetadata(DLDD key, DDD value);
+ const char* repGetMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, const char** className, const char** namespaceName);
+
void recGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes, DWORD result);
void dmpGetJitFlags(DWORD key, DD value);
DWORD repGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes);
@@ -1247,7 +1257,7 @@ private:
};
// ********************* Please keep this up-to-date to ease adding more ***************
-// Highest packet number: 160
+// Highest packet number: 161
// *************************************************************************************
enum mcPackets
{
@@ -1342,6 +1352,7 @@ enum mcPackets
Packet_GetMethodHash = 73,
Packet_GetMethodInfo = 74,
Packet_GetMethodName = 75,
+ Packet_GetMethodNameFromMetadata = 161, // Added 9/6/17
Packet_GetMethodSig = 76,
Packet_GetMethodSync = 77,
Packet_GetMethodVTableOffset = 78,
diff --git a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
index d79e4ee51a..2a477a07e3 100644
--- a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
+++ b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
@@ -1367,6 +1367,17 @@ const char* interceptor_ICJI::getMethodName(CORINFO_METHOD_HANDLE ftn, /*
return temp;
}
+const char* interceptor_ICJI::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char** className, /* OUT */
+ const char** namespaceName /* OUT */
+ )
+{
+ mc->cr->AddCall("getMethodNameFromMetadata");
+ const char* temp = original_ICorJitInfo->getMethodNameFromMetadata(ftn, className, namespaceName);
+ mc->recGetMethodNameFromMetadata(ftn, (char*)temp, className, namespaceName);
+ return temp;
+}
+
// this function is for debugging only. It returns a value that
// is will always be the same for a given method. It is used
// to implement the 'jitRange' functionality
diff --git a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
index d731a773f0..a54ead5661 100644
--- a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
+++ b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
@@ -1080,6 +1080,15 @@ const char* interceptor_ICJI::getMethodName(CORINFO_METHOD_HANDLE ftn, /*
return original_ICorJitInfo->getMethodName(ftn, moduleName);
}
+const char* interceptor_ICJI::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char** className, /* OUT */
+ const char** namespaceName /* OUT */
+ )
+{
+ mcs->AddCall("getMethodNameFromMetadata");
+ return original_ICorJitInfo->getMethodNameFromMetadata(ftn, className, namespaceName);
+}
+
// this function is for debugging only. It returns a value that
// is will always be the same for a given method. It is used
// to implement the 'jitRange' functionality
diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
index fd45a3c2dc..7e0ded9f0f 100644
--- a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
+++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
@@ -974,6 +974,14 @@ const char* interceptor_ICJI::getMethodName(CORINFO_METHOD_HANDLE ftn, /*
return original_ICorJitInfo->getMethodName(ftn, moduleName);
}
+const char* interceptor_ICJI::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char** className, /* OUT */
+ const char** namespaceName /* OUT */
+ )
+{
+ return original_ICorJitInfo->getMethodNameFromMetadata(ftn, className, namespaceName);
+}
+
// this function is for debugging only. It returns a value that
// is will always be the same for a given method. It is used
// to implement the 'jitRange' functionality
diff --git a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
index e8b4187a99..2e78113991 100644
--- a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
+++ b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
@@ -1183,6 +1183,15 @@ const char* MyICJI::getMethodName(CORINFO_METHOD_HANDLE ftn, /* IN */
return jitInstance->mc->repGetMethodName(ftn, moduleName);
}
+const char* MyICJI::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char** className, /* OUT */
+ const char** namespaceName /* OUT */
+ )
+{
+ jitInstance->mc->cr->AddCall("getMethodNameFromMetadata");
+ return jitInstance->mc->repGetMethodNameFromMetadata(ftn, className, namespaceName);
+}
+
// this function is for debugging only. It returns a value that
// is will always be the same for a given method. It is used
// to implement the 'jitRange' functionality
diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h
index 084b9841bb..3171d6b00d 100644
--- a/src/inc/corinfo.h
+++ b/src/inc/corinfo.h
@@ -213,11 +213,11 @@ TODO: Talk about initializing strutures before use
#define SELECTANY extern __declspec(selectany)
#endif
-SELECTANY const GUID JITEEVersionIdentifier = { /* 5a1cfc89-a84a-4642-b01d-ead88e60c1ee */
- 0x5a1cfc89,
- 0xa84a,
- 0x4642,
- { 0xb0, 0x1d, 0xea, 0xd8, 0x8e, 0x60, 0xc1, 0xee }
+SELECTANY const GUID JITEEVersionIdentifier = { /* 7f70c266-eada-427b-be8a-be1260e34b1b */
+ 0x7f70c266,
+ 0xeada,
+ 0x427b,
+ {0xbe, 0x8a, 0xbe, 0x12, 0x60, 0xe3, 0x4b, 0x1b}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -827,7 +827,7 @@ enum CorInfoFlag
CORINFO_FLG_NOSECURITYWRAP = 0x04000000, // The method requires no security checks
CORINFO_FLG_DONT_INLINE = 0x10000000, // The method should not be inlined
CORINFO_FLG_DONT_INLINE_CALLER = 0x20000000, // The method should not be inlined, nor should its callers. It cannot be tail called.
-// CORINFO_FLG_UNUSED = 0x40000000,
+ CORINFO_FLG_JIT_INTRINSIC = 0x40000000, // Method is a potential jit intrinsic; verify identity by name check
// These are internal flags that can only be on Classes
CORINFO_FLG_VALUECLASS = 0x00010000, // is the class a value class
@@ -2260,7 +2260,6 @@ public:
CORINFO_CLASS_HANDLE cls
) = 0;
-
// Append a (possibly truncated) representation of the type cls to the preallocated buffer ppBuf of length pnBufLen
// If fNamespace=TRUE, include the namespace/enclosing classes
// If fFullInst=TRUE (regardless of fNamespace and fAssembly), include namespace and assembly for any type parameters
@@ -2791,6 +2790,15 @@ public:
const char **moduleName /* OUT */
) = 0;
+ // Return method name as in metadata, or nullptr if there is none,
+ // and optionally return the class and namespace names as in metadata.
+ // Suitable for non-debugging use.
+ virtual const char* getMethodNameFromMetadata(
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char **className, /* OUT */
+ const char **namespaceName /* OUT */
+ ) = 0;
+
// this function is for debugging only. It returns a value that
// is will always be the same for a given method. It is used
// to implement the 'jitRange' functionality
diff --git a/src/jit/ICorJitInfo_API_names.h b/src/jit/ICorJitInfo_API_names.h
index 1330f81097..34a8bc0626 100644
--- a/src/jit/ICorJitInfo_API_names.h
+++ b/src/jit/ICorJitInfo_API_names.h
@@ -106,6 +106,7 @@ DEF_CLR_API(getEEInfo)
DEF_CLR_API(getJitTimeLogFilename)
DEF_CLR_API(getMethodDefFromMethod)
DEF_CLR_API(getMethodName)
+DEF_CLR_API(getMethodNameFromMetadata)
DEF_CLR_API(getMethodHash)
DEF_CLR_API(findNameOfToken)
DEF_CLR_API(getSystemVAmd64PassStructInRegisterDescriptor)
diff --git a/src/jit/ICorJitInfo_API_wrapper.hpp b/src/jit/ICorJitInfo_API_wrapper.hpp
index 1d30e0096e..78177e16d7 100644
--- a/src/jit/ICorJitInfo_API_wrapper.hpp
+++ b/src/jit/ICorJitInfo_API_wrapper.hpp
@@ -1029,6 +1029,17 @@ const char* WrapICorJitInfo::getMethodName(
return temp;
}
+const char* WrapICorJitInfo::getMethodNameFromMetadata(
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char **className, /* OUT */
+ const char **namespaceName /* OUT */)
+{
+ API_ENTER(getMethodNameFromMetadata);
+ const char* temp = wrapHnd->getMethodNameFromMetaData(ftn, moduleName, namespaceName);
+ API_LEAVE(getMethodNameFromMetadata);
+ return temp;
+}
+
unsigned WrapICorJitInfo::getMethodHash(
CORINFO_METHOD_HANDLE ftn /* IN */)
{
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index dd8f91369d..01997f1665 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -2980,6 +2980,7 @@ protected:
int memberRef,
bool readonlyCall,
bool tailCall,
+ bool isJitIntrinsic,
CorInfoIntrinsics* pIntrinsicID);
GenTreePtr impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
CORINFO_SIG_INFO* sig,
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index e829d9a3b0..dab2ee30a3 100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -3281,12 +3281,21 @@ GenTreePtr Compiler::impIntrinsic(GenTreePtr newobjThis,
int memberRef,
bool readonlyCall,
bool tailCall,
+ bool isJitIntrinsic,
CorInfoIntrinsics* pIntrinsicID)
{
bool mustExpand = false;
CorInfoIntrinsics intrinsicID = info.compCompHnd->getIntrinsicID(method, &mustExpand);
*pIntrinsicID = intrinsicID;
+ // Jit intrinsics are always optional to expand, and won't have an
+ // Intrinsic ID.
+ if (isJitIntrinsic)
+ {
+ assert(!mustExpand);
+ assert(intrinsicID == CORINFO_INTRINSIC_Illegal);
+ }
+
#ifndef _TARGET_ARM_
genTreeOps interlockedOperator;
#endif
@@ -3755,6 +3764,29 @@ GenTreePtr Compiler::impIntrinsic(GenTreePtr newobjThis,
break;
}
+#ifdef DEBUG
+ // Sample code showing how to use the new intrinsic mechansim.
+ if (isJitIntrinsic)
+ {
+ assert(retNode == nullptr);
+ const char* className = nullptr;
+ const char* namespaceName = nullptr;
+ const char* methodName = info.compCompHnd->getMethodNameFromMetadata(method, &className, &namespaceName);
+
+ if ((namespaceName != nullptr) && strcmp(namespaceName, "System") == 0)
+ {
+ if ((className != nullptr) && strcmp(className, "Enum") == 0)
+ {
+ if ((methodName != nullptr) && strcmp(methodName, "HasFlag") == 0)
+ {
+ // Todo: plug in the intrinsic expansion
+ JITDUMP("Found Intrinsic call to Enum.HasFlag\n");
+ }
+ }
+ }
+ }
+#endif
+
if (mustExpand)
{
if (retNode == nullptr)
@@ -6776,10 +6808,12 @@ var_types Compiler::impImportCall(OPCODE opcode,
#endif // DEBUG
// <NICE> Factor this into getCallInfo </NICE>
- if ((mflags & CORINFO_FLG_INTRINSIC) && !pConstrainedResolvedToken)
+ const bool isIntrinsic = (mflags & CORINFO_FLG_INTRINSIC) != 0;
+ const bool isJitIntrinsic = (mflags & CORINFO_FLG_JIT_INTRINSIC) != 0;
+ if ((isIntrinsic || isJitIntrinsic) && !pConstrainedResolvedToken)
{
call = impIntrinsic(newobjThis, clsHnd, methHnd, sig, pResolvedToken->token, readonlyCall,
- (canTailCall && (tailCall != 0)), &intrinsicID);
+ (canTailCall && (tailCall != 0)), isJitIntrinsic, &intrinsicID);
if (compIsForInlining() && compInlineResult->IsFailure())
{
diff --git a/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems b/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
index bd68b542f1..bc7e039989 100644
--- a/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
+++ b/src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
@@ -336,6 +336,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IndexerNameAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\INotifyCompletion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\InternalsVisibleToAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IntrinsicAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IsConst.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IsByRefLikeAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IsVolatile.cs" />
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs
new file mode 100644
index 0000000000..0d249deaf4
--- /dev/null
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Calls to methods marked with this attribute may be replaced at
+ // some call sites with jit intrinsic expansions.
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)]
+ internal sealed class IntrinsicAttribute : Attribute
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Enum.cs b/src/mscorlib/src/System/Enum.cs
index 092bea1a29..b5d00fe60e 100644
--- a/src/mscorlib/src/System/Enum.cs
+++ b/src/mscorlib/src/System/Enum.cs
@@ -12,6 +12,18 @@ using System.Runtime.Versioning;
using System.Diagnostics;
using System.Diagnostics.Contracts;
+// The code below includes partial support for float/double and
+// pointer sized enums.
+//
+// The type loader does not prohibit such enums, and older versions of
+// the ECMA spec include them as possible enum types.
+//
+// However there are many things broken throughout the stack for
+// float/double/intptr/uintptr enums. There was a conscious decision
+// made to not fix the whole stack to work well for them because of
+// the right behavior is often unclear, and it is hard to test and
+// very low value because of such enums cannot be expressed in C#.
+
namespace System
{
[Serializable]
@@ -961,6 +973,7 @@ namespace System
return ToString();
}
+ [Intrinsic]
public Boolean HasFlag(Enum flag)
{
if (flag == null)
diff --git a/src/vm/classnames.h b/src/vm/classnames.h
index 0c24914a56..fc087372c8 100644
--- a/src/vm/classnames.h
+++ b/src/vm/classnames.h
@@ -145,6 +145,7 @@
#define g_CompilerServicesFixedAddressValueTypeAttribute "System.Runtime.CompilerServices.FixedAddressValueTypeAttribute"
#define g_CompilerServicesUnsafeValueTypeAttribute "System.Runtime.CompilerServices.UnsafeValueTypeAttribute"
+#define g_CompilerServicesIntrinsicAttribute "System.Runtime.CompilerServices.IntrinsicAttribute"
#define g_UnmanagedFunctionPointerAttribute "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"
#define g_DefaultDllImportSearchPathsAttribute "System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute"
#define g_NativeCallableAttribute "System.Runtime.InteropServices.NativeCallableAttribute"
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp
index 71af406d04..4301873df8 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -6460,6 +6460,48 @@ const char* CEEInfo::getMethodName (CORINFO_METHOD_HANDLE ftnHnd, const char** s
return result;
}
+const char* CEEInfo::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftnHnd, const char** className, const char** namespaceName)
+{
+ CONTRACTL {
+ SO_TOLERANT;
+ THROWS;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ } CONTRACTL_END;
+
+ const char* result = NULL;
+ const char* classResult = NULL;
+ const char* namespaceResult = NULL;
+
+ JIT_TO_EE_TRANSITION();
+
+ MethodDesc *ftn = GetMethod(ftnHnd);
+ mdMethodDef token = ftn->GetMemberDef();
+
+ if (!IsNilToken(token))
+ {
+ if (!FAILED(ftn->GetMDImport()->GetNameOfMethodDef(token, &result)))
+ {
+ MethodTable* pMT = ftn->GetMethodTable();
+ classResult = pMT->GetFullyQualifiedNameInfo(&namespaceResult);
+ }
+ }
+
+ if (className != NULL)
+ {
+ *className = classResult;
+ }
+
+ if (namespaceName != NULL)
+ {
+ *namespaceName = namespaceResult;
+ }
+
+ EE_TO_JIT_TRANSITION();
+
+ return result;
+}
+
/*********************************************************************/
DWORD CEEInfo::getMethodAttribs (CORINFO_METHOD_HANDLE ftn)
{
@@ -6514,6 +6556,8 @@ DWORD CEEInfo::getMethodAttribsInternal (CORINFO_METHOD_HANDLE ftn)
result |= CORINFO_FLG_SYNCH;
if (pMD->IsFCallOrIntrinsic())
result |= CORINFO_FLG_NOGCCHECK | CORINFO_FLG_INTRINSIC;
+ if (pMD->IsJitIntrinsic())
+ result |= CORINFO_FLG_JIT_INTRINSIC;
if (IsMdVirtual(attribs))
result |= CORINFO_FLG_VIRTUAL;
if (IsMdAbstract(attribs))
diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h
index 141c812280..8ba65c3964 100644
--- a/src/vm/jitinterface.h
+++ b/src/vm/jitinterface.h
@@ -649,6 +649,7 @@ public:
// ICorMethodInfo stuff
const char* getMethodName (CORINFO_METHOD_HANDLE ftnHnd, const char** scopeName);
+ const char* getMethodNameFromMetadata (CORINFO_METHOD_HANDLE ftnHnd, const char** className, const char** namespaceName);
unsigned getMethodHash (CORINFO_METHOD_HANDLE ftnHnd);
DWORD getMethodAttribs (CORINFO_METHOD_HANDLE ftnHnd);
diff --git a/src/vm/method.hpp b/src/vm/method.hpp
index 671fd82b7f..9a20af2212 100644
--- a/src/vm/method.hpp
+++ b/src/vm/method.hpp
@@ -704,7 +704,6 @@ public:
InterlockedUpdateFlags(mdcNotInline, set);
}
-
BOOL IsIntrospectionOnly();
#ifndef DACCESS_COMPILE
VOID EnsureActive();
@@ -1690,7 +1689,8 @@ protected:
enum_flag2_IsUnboxingStub = 0x04,
enum_flag2_HasNativeCodeSlot = 0x08, // Has slot for native code
- // unused = 0x10,
+ enum_flag2_IsJitIntrinsic = 0x10, // Jit may expand method as an intrinsic
+
// unused = 0x20,
// unused = 0x40,
// unused = 0x80,
@@ -1743,6 +1743,18 @@ public:
m_bFlags2 |= enum_flag2_HasNativeCodeSlot;
}
+ inline BOOL IsJitIntrinsic()
+ {
+ LIMITED_METHOD_DAC_CONTRACT;
+ return (m_bFlags2 & enum_flag2_IsJitIntrinsic) != 0;
+ }
+
+ inline void SetIsJitIntrinsic()
+ {
+ LIMITED_METHOD_CONTRACT;
+ m_bFlags2 |= enum_flag2_IsJitIntrinsic;
+ }
+
static const SIZE_T s_ClassificationSizeTable[];
static SIZE_T GetBaseSize(DWORD classification)
diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp
index 4768807652..cdee2d8667 100644
--- a/src/vm/methodtablebuilder.cpp
+++ b/src/vm/methodtablebuilder.cpp
@@ -5082,6 +5082,20 @@ MethodTableBuilder::InitNewMethodDesc(
pNewMD->SetNotInline(true);
}
+ // Check for methods marked as [Intrinsic]
+ if (GetModule()->IsSystem())
+ {
+ HRESULT hr = GetMDImport()->GetCustomAttributeByName(pMethod->GetMethodSignature().GetToken(),
+ g_CompilerServicesIntrinsicAttribute,
+ NULL,
+ NULL);
+
+ if (hr == S_OK)
+ {
+ pNewMD->SetIsJitIntrinsic();
+ }
+ }
+
pNewMD->SetSlot(pMethod->GetSlotIndex());
}
diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp
index 5683f4f3e1..b8ef3eab91 100644
--- a/src/zap/zapinfo.cpp
+++ b/src/zap/zapinfo.cpp
@@ -3545,6 +3545,11 @@ const char* ZapInfo::getMethodName(CORINFO_METHOD_HANDLE ftn, const char **modul
return m_pEEJitInfo->getMethodName(ftn, moduleName);
}
+const char* ZapInfo::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, const char **className, const char** namespaceName)
+{
+ return m_pEEJitInfo->getMethodNameFromMetadata(ftn, className, namespaceName);
+}
+
unsigned ZapInfo::getMethodHash(CORINFO_METHOD_HANDLE ftn)
{
return m_pEEJitInfo->getMethodHash(ftn);
diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h
index 88f095bc2d..d533975c79 100644
--- a/src/zap/zapinfo.h
+++ b/src/zap/zapinfo.h
@@ -616,6 +616,10 @@ public:
const char* getMethodName(CORINFO_METHOD_HANDLE ftn,
const char **moduleName);
+ const char* getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn,
+ const char **className,
+ const char **namespaceName);
+
unsigned getMethodHash(CORINFO_METHOD_HANDLE ftn);
DWORD getMethodAttribs(CORINFO_METHOD_HANDLE ftn);
void setMethodAttribs(CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs);