From 35c23eccfdeaddbd07cd39473fe7544603e67857 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Mon, 30 Jan 2017 15:45:11 -0800 Subject: Jit interface support for devirtualization Add new method to jit interface so the jit can determine what derived method might be called for a given base method, derived class pair. Implement support in the VM and in other places (zap, spmi). --- .../superpmi/superpmi-shared/icorjitinfoimpl.h | 7 +++++ src/ToolBox/superpmi/superpmi-shared/lwmlist.h | 1 + .../superpmi/superpmi-shared/methodcontext.cpp | 36 +++++++++++++++++++++- .../superpmi/superpmi-shared/methodcontext.h | 7 ++++- .../superpmi-shim-collector/icorjitinfo.cpp | 13 ++++++++ .../superpmi/superpmi-shim-counter/icorjitinfo.cpp | 11 +++++++ .../superpmi/superpmi-shim-simple/icorjitinfo.cpp | 10 ++++++ src/ToolBox/superpmi/superpmi/icorjitinfo.cpp | 12 ++++++++ 8 files changed, 95 insertions(+), 2 deletions(-) (limited to 'src/ToolBox') diff --git a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h index b847d9bc50..4c1aa3d72d 100644 --- a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h +++ b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h @@ -125,6 +125,13 @@ public: 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. diff --git a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h index de0db3a9bb..8e19656f18 100644 --- a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h +++ b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h @@ -141,6 +141,7 @@ LWM(IsWriteBarrierHelperRequired, DWORDLONG, DWORD) 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) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index 5768d38569..c60b593ae0 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -3296,6 +3296,40 @@ void MethodContext::repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method, unsig 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 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) @@ -6165,7 +6199,7 @@ mdMethodDef MethodContext::repGetMethodDefFromMethod(CORINFO_METHOD_HANDLE hMeth int index = GetMethodDefFromMethod->GetIndex((DWORDLONG)hMethod); if (index < 0) - return (mdMethodDef)0x06000001; + return (mdMethodDef)0x06000001; return (mdMethodDef)GetMethodDefFromMethod->Get((DWORDLONG)hMethod); } diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h index 0d49666e5c..ee2d4ac7c8 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -698,6 +698,10 @@ public: 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); @@ -1016,7 +1020,7 @@ private: // ********************* Please keep this up-to-date to ease adding more *************** -// Highest packet number: 159 +// Highest packet number: 160 // ************************************************************************************* enum mcPackets { @@ -1151,6 +1155,7 @@ 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, diff --git a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 1813ed29ff..bb19cab455 100644 --- a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -236,6 +236,19 @@ void interceptor_ICJI::getMethodVTableOffset ( 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( diff --git a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 448fb1f686..beff1f4e4b 100644 --- a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -165,6 +165,17 @@ void interceptor_ICJI::getMethodVTableOffset ( 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( diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 4d145f6a41..9e229eeeaf 100644 --- a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -153,6 +153,16 @@ void interceptor_ICJI::getMethodVTableOffset ( 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( diff --git a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp index b746d3f6f7..ae4ba9917c 100644 --- a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -185,6 +185,18 @@ void MyICJI::getMethodVTableOffset ( 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( -- cgit v1.2.3