diff options
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); |