unsigned* offsetAfterIndirection /* OUT */
);
+ // Find the virtual method in implementingClass that overrides virtualMethod.
+ // Return null if devirtualization is not possible.
+ CORINFO_METHOD_HANDLE resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod,
+ CORINFO_CLASS_HANDLE implementingClass
+ );
+
// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
// getIntrinsicID() returns the intrinsic ID.
// *pMustExpand tells whether or not JIT must expand the intrinsic.
LWM(MergeClasses, DLDL, DWORDLONG)
LWM(PInvokeMarshalingRequired, Agnostic_PInvokeMarshalingRequired, DWORD)
LWM(ResolveToken, Agnostic_CORINFO_RESOLVED_TOKENin, Agnostic_CORINFO_RESOLVED_TOKENout)
+LWM(ResolveVirtualMethod, DLDL, DWORDLONG)
LWM(TryResolveToken, Agnostic_CORINFO_RESOLVED_TOKENin, Agnostic_CORINFO_RESOLVED_TOKENout)
LWM(SatisfiesClassConstraints, DWORDLONG, DWORD)
LWM(SatisfiesMethodConstraints, DLDL, DWORD)
DEBUG_REP(dmpGetMethodVTableOffset((DWORDLONG)method, value));
}
+void MethodContext::recResolveVirtualMethod(CORINFO_METHOD_HANDLE virtMethod, CORINFO_CLASS_HANDLE implClass, CORINFO_METHOD_HANDLE result)
+{
+ if (ResolveVirtualMethod == nullptr)
+ {
+ ResolveVirtualMethod = new LightWeightMap<DLDL, DWORDLONG>();
+ }
+
+ DLDL key;
+ key.A = (DWORDLONG)virtMethod;
+ key.B = (DWORDLONG)implClass;
+ ResolveVirtualMethod->Add(key, (DWORDLONG) result);
+ DEBUG_REC(dmpResolveVirtualMethod(key, result));
+}
+
+void MethodContext::dmpResolveVirtualMethod(DLDL key, DWORDLONG value)
+{
+ printf("ResolveVirtualMethod virtMethod-%016llX, implClass-%016llX, result-%016llX", key.A, key.B, value);
+}
+
+CORINFO_METHOD_HANDLE MethodContext::repResolveVirtualMethod(CORINFO_METHOD_HANDLE virtMethod, CORINFO_CLASS_HANDLE implClass)
+{
+ DLDL key;
+ key.A = (DWORDLONG)virtMethod;
+ key.B = (DWORDLONG)implClass;
+
+ AssertCodeMsg(ResolveVirtualMethod != nullptr, EXCEPTIONCODE_MC, "No ResolveVirtualMap map for %016llX-%016llX", key.A, key.B);
+ AssertCodeMsg(ResolveVirtualMethod->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX-%016llx", key.A, key.B);
+ DWORDLONG result = ResolveVirtualMethod->Get(key);
+
+ DEBUG_REP(dmpResolveVirtualMethod(key, result));
+
+ return (CORINFO_METHOD_HANDLE)result;
+}
+
void MethodContext::recGetTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_CLASS_HANDLE result)
{
if (GetTokenTypeAsHandle == nullptr)
int index = GetMethodDefFromMethod->GetIndex((DWORDLONG)hMethod);
if (index < 0)
- return (mdMethodDef)0x06000001;
+ return (mdMethodDef)0x06000001;
return (mdMethodDef)GetMethodDefFromMethod->Get((DWORDLONG)hMethod);
}
void dmpGetMethodVTableOffset(DWORDLONG key, DD value);
void repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method, unsigned *offsetOfIndirection, unsigned* offsetAfterIndirection);
+ void recResolveVirtualMethod(CORINFO_METHOD_HANDLE virtMethod, CORINFO_CLASS_HANDLE implClass, CORINFO_METHOD_HANDLE result);
+ void dmpResolveVirtualMethod(DLDL key, DWORDLONG value);
+ CORINFO_METHOD_HANDLE repResolveVirtualMethod(CORINFO_METHOD_HANDLE virtMethod, CORINFO_CLASS_HANDLE implClass);
+
void recGetTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_CLASS_HANDLE result);
void dmpGetTokenTypeAsHandle(const Agnostic_CORINFO_RESOLVED_TOKEN& key, DWORDLONG value);
CORINFO_CLASS_HANDLE repGetTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken);
// ********************* Please keep this up-to-date to ease adding more ***************
-// Highest packet number: 159
+// Highest packet number: 160
// *************************************************************************************
enum mcPackets
{
Packet_MergeClasses = 107,
Packet_PInvokeMarshalingRequired = 108,
Packet_ResolveToken = 109,
+ Packet_ResolveVirtualMethod = 160, // Added 2/13/17
Packet_TryResolveToken = 158, //Added 4/26/2016
Packet_SatisfiesClassConstraints = 110,
Packet_SatisfiesMethodConstraints = 111,
mc->recGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
}
+// Find the virtual method in implementingClass that overrides virtualMethod.
+// Return null if devirtualization is not possible.
+CORINFO_METHOD_HANDLE interceptor_ICJI::resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod,
+ CORINFO_CLASS_HANDLE implementingClass
+ )
+{
+ mc->cr->AddCall("resolveVirtualMethod");
+ CORINFO_METHOD_HANDLE result = original_ICorJitInfo->resolveVirtualMethod(virtualMethod, implementingClass);
+ mc->recResolveVirtualMethod(virtualMethod, implementingClass, result);
+ return result;
+}
+
// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
// getIntrinsicID() returns the intrinsic ID.
CorInfoIntrinsics interceptor_ICJI::getIntrinsicID(
original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
}
+// Find the virtual method in implementingClass that overrides virtualMethod.
+// Return null if devirtualization is not possible.
+CORINFO_METHOD_HANDLE interceptor_ICJI::resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod,
+ CORINFO_CLASS_HANDLE implementingClass
+ )
+{
+ mcs->AddCall("resolveVirtualMethod");
+ return original_ICorJitInfo->resolveVirtualMethod(virtualMethod, implementingClass);
+}
+
// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
// getIntrinsicID() returns the intrinsic ID.
CorInfoIntrinsics interceptor_ICJI::getIntrinsicID(
original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
}
+// Find the virtual method in implementingClass that overrides virtualMethod.
+// Return null if devirtualization is not possible.
+CORINFO_METHOD_HANDLE interceptor_ICJI::resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod,
+ CORINFO_CLASS_HANDLE implementingClass
+ )
+{
+ return original_ICorJitInfo->resolveVirtualMethod(virtualMethod, implementingClass);
+}
+
// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
// getIntrinsicID() returns the intrinsic ID.
CorInfoIntrinsics interceptor_ICJI::getIntrinsicID(
jitInstance->mc->repGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
}
+// Find the virtual method in implementingClass that overrides virtualMethod.
+// Return null if devirtualization is not possible.
+CORINFO_METHOD_HANDLE MyICJI::resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod,
+ CORINFO_CLASS_HANDLE implementingClass
+ )
+{
+ jitInstance->mc->cr->AddCall("resolveVirtualMethod");
+ CORINFO_METHOD_HANDLE result = jitInstance->mc->repResolveVirtualMethod(virtualMethod, implementingClass);
+ return result;
+}
+
// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
// getIntrinsicID() returns the intrinsic ID.
CorInfoIntrinsics MyICJI::getIntrinsicID(
#if COR_JIT_EE_VERSION > 460
// Update this one
-SELECTANY const GUID JITEEVersionIdentifier = { /* 4bd06266-8ef7-4172-bec6-d3149fde7859 */
- 0x4bd06266,
- 0x8ef7,
- 0x4172,
- {0xbe, 0xc6, 0xd3, 0x14, 0x9f, 0xde, 0x78, 0x59}
-};
+SELECTANY const GUID JITEEVersionIdentifier = { /* cda334f7-0020-4622-a4a5-8b8ac71ee5cf */
+ 0xcda334f7,
+ 0x0020,
+ 0x4622,
+ {0xa4, 0xa5, 0x8b, 0x8a, 0xc7, 0x1e, 0xe5, 0xcf}
+ };
#else
unsigned* offsetAfterIndirection /* OUT */
) = 0;
+#if COR_JIT_EE_VERSION > 460
+ // Find the virtual method in implementingClass that overrides virtualMethod.
+ // Return null if devirtualization is not possible.
+ virtual CORINFO_METHOD_HANDLE resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod, /* IN */
+ CORINFO_CLASS_HANDLE implementingClass /* IN */
+ ) = 0;
+#endif
+
// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
// getIntrinsicID() returns the intrinsic ID.
// *pMustExpand tells whether or not JIT must expand the intrinsic.
}
/*********************************************************************/
+CORINFO_METHOD_HANDLE CEEInfo::resolveVirtualMethod(CORINFO_METHOD_HANDLE methodHnd,
+ CORINFO_CLASS_HANDLE derivedClass)
+{
+ CONTRACTL {
+ SO_TOLERANT;
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_PREEMPTIVE;
+ } CONTRACTL_END;
+
+ CORINFO_METHOD_HANDLE result = nullptr;
+
+ JIT_TO_EE_TRANSITION();
+
+ MethodDesc* method = GetMethod(methodHnd);
+
+ // Method better be from a fully loaded class
+ _ASSERTE(method->IsRestored() && method->GetMethodTable()->IsFullyLoaded());
+
+ // Method better be virtual
+ _ASSERTE(method->IsVirtual());
+
+ //@GENERICS: shouldn't be doing this for instantiated methods as they live elsewhere
+ _ASSERTE(!method->HasMethodInstantiation());
+
+ // Method's class better not be an interface
+ _ASSERTE(!method->GetMethodTable()->IsInterface());
+
+ // Method better be in the vtable
+ WORD slot = method->GetSlot();
+ _ASSERTE(slot < method->GetMethodTable()->GetNumVirtuals());
+
+ // TODO: Derived class should have base class as parent...
+ TypeHandle DerivedClsHnd(derivedClass);
+
+ // If derived class is _Canon, we can't devirtualize.
+ if (DerivedClsHnd != TypeHandle(g_pCanonMethodTableClass))
+ {
+ MethodTable* pMT = DerivedClsHnd.GetMethodTable();
+
+ // MethodDescs returned to JIT at runtime are always fully loaded. Verify that it is the case.
+ _ASSERTE(pMT->IsRestored() && pMT->IsFullyLoaded());
+
+ MethodDesc* pDevirtMD = pMT->GetMethodDescForSlot(slot);
+
+ _ASSERTE(pDevirtMD->IsRestored());
+
+ // Allow devirtialization if jitting, or if prejitting and the
+ // method being jitted, the devirtualized class, and the
+ // devirtualized method are all in the same versioning bubble.
+ bool allowDevirt = true;
+
+#ifdef FEATURE_READYTORUN_COMPILER
+ if (IsReadyToRunCompilation())
+ {
+ Assembly * pCallerAssembly = m_pMethodBeingCompiled->GetModule()->GetAssembly();
+ allowDevirt =
+ IsInSameVersionBubble(pCallerAssembly , pDevirtMD->GetModule()->GetAssembly())
+ && IsInSameVersionBubble(pCallerAssembly , pMT->GetAssembly());
+ }
+#endif
+
+ if (allowDevirt)
+ {
+ result = (CORINFO_METHOD_HANDLE) pDevirtMD;
+ }
+ }
+
+ EE_TO_JIT_TRANSITION();
+
+ return result;
+}
+
+/*********************************************************************/
void CEEInfo::getFunctionEntryPoint(CORINFO_METHOD_HANDLE ftnHnd,
CORINFO_CONST_LOOKUP * pResult,
CORINFO_ACCESS_FLAGS accessFlags)
unsigned * pOffsetAfterIndirection
);
+ CORINFO_METHOD_HANDLE resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod,
+ CORINFO_CLASS_HANDLE implementingClass
+ );
+
CorInfoIntrinsics getIntrinsicID(CORINFO_METHOD_HANDLE method,
bool * pMustExpand = NULL);
m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection);
}
+CORINFO_METHOD_HANDLE ZapInfo::resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod,
+ CORINFO_CLASS_HANDLE implementingClass
+ )
+{
+ return m_pEEJitInfo->resolveVirtualMethod(virtualMethod, implementingClass);
+}
+
CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method,
bool * pMustExpand)
{
unsigned * pOffsetOfIndirection,
unsigned * pOffsetAfterIndirection);
+ CORINFO_METHOD_HANDLE resolveVirtualMethod(
+ CORINFO_METHOD_HANDLE virtualMethod,
+ CORINFO_CLASS_HANDLE implementingClass
+ );
+
CorInfoIntrinsics getIntrinsicID(CORINFO_METHOD_HANDLE method,
bool * pMustExpand = NULL);
bool isInSIMDModule(CORINFO_CLASS_HANDLE classHnd);