diff options
author | Andy Ayers <andya@microsoft.com> | 2017-10-23 17:46:41 -0700 |
---|---|---|
committer | Andy Ayers <andya@microsoft.com> | 2017-10-30 14:36:24 -0700 |
commit | 215ee89756e612bcdd7e9bd61ea500eacaf4973f (patch) | |
tree | 1ba04645996fd4c04db80c1975a1fbd3ef791568 /src/ToolBox | |
parent | 274c961fa23d3dcd38cbb5736dcbf7b908d0cf99 (diff) | |
download | coreclr-215ee89756e612bcdd7e9bd61ea500eacaf4973f.tar.gz coreclr-215ee89756e612bcdd7e9bd61ea500eacaf4973f.tar.bz2 coreclr-215ee89756e612bcdd7e9bd61ea500eacaf4973f.zip |
JIT: optimize calls on boxed objects
For calls with boxed this objects, invoke the unboxed entry point if available
and modify the box to copy the original value or struct to a local. Pass the
address of this local as the first argument to the unboxed entry point.
Defer for cases where the unboxed entry point requires an extra type parameter.
This may enable subsequent inlining of the method, and if the method has other
boxed parameters, may enable undoing those boxes as well.
The jit is not yet as proficient at eliminating the struct copies, but they
are present with or without this change, and some may even be required when the
methods mutate the fields of `this`.
Closes #14213.
Diffstat (limited to 'src/ToolBox')
8 files changed, 101 insertions, 1 deletions
diff --git a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h index 64a9619e9f..5c6dc4fc04 100644 --- a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h +++ b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h @@ -121,6 +121,11 @@ CORINFO_METHOD_HANDLE resolveVirtualMethod(CORINFO_METHOD_HANDLE virtualMethod, CORINFO_CLASS_HANDLE implementingClass, CORINFO_CONTEXT_HANDLE ownerType); +// Get the unboxed entry point for a method, if possible. +CORINFO_METHOD_HANDLE getUnboxedEntry( + CORINFO_METHOD_HANDLE ftn, + bool* requiresInstMethodTableArg /* OUT */); + // Given T, return the type of the default EqualityComparer<T>. // Returns null if the type can't be determined exactly. CORINFO_CLASS_HANDLE getDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE elemType); diff --git a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h index b2f69af782..b0cb7ad3c8 100644 --- a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h +++ b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h @@ -124,6 +124,7 @@ LWM(GetThreadTLSIndex, DWORD, DLD) LWM(GetTokenTypeAsHandle, GetTokenTypeAsHandleValue, DWORDLONG) LWM(GetTypeForBox, DWORDLONG, DWORDLONG) LWM(GetTypeForPrimitiveValueClass, DWORDLONG, DWORD) +LWM(GetUnboxedEntry, DWORDLONG, DLD); LWM(GetUnBoxHelper, DWORDLONG, DWORD) LWM(GetUnmanagedCallConv, DWORDLONG, DWORD) LWM(GetVarArgsHandle, GetVarArgsHandleValue, DLDL) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index 0ee17c9104..3326a49937 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -3018,6 +3018,55 @@ CORINFO_METHOD_HANDLE MethodContext::repResolveVirtualMethod(CORINFO_METHOD_HAND return (CORINFO_METHOD_HANDLE)result; } +void MethodContext::recGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, + bool *requiresInstMethodTableArg, + CORINFO_METHOD_HANDLE result) +{ + if (GetUnboxedEntry == nullptr) + { + GetUnboxedEntry = new LightWeightMap<DWORDLONG, DLD>(); + } + + DWORDLONG key = (DWORDLONG) ftn; + DLD value; + value.A = (DWORDLONG) result; + if (requiresInstMethodTableArg != nullptr) + { + value.B = (DWORD) *requiresInstMethodTableArg ? 1 : 0; + } + else + { + value.B = 0; + } + GetUnboxedEntry->Add(key, value); + DEBUG_REC(dmpGetUnboxedEntry(key, value)); +} + +void MethodContext::dmpGetUnboxedEntry(DWORDLONG key, DLD value) +{ + printf("GetUnboxedEntry ftn-%016llX, result-%016llX, requires-inst-%u", + key, value.A, value.B); +} + +CORINFO_METHOD_HANDLE MethodContext::repGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, + bool* requiresInstMethodTableArg) +{ + DWORDLONG key = (DWORDLONG)ftn; + + AssertCodeMsg(GetUnboxedEntry != nullptr, EXCEPTIONCODE_MC, "No GetUnboxedEntry map for %016llX", key); + AssertCodeMsg(GetUnboxedEntry->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX", key); + DLD result = GetUnboxedEntry->Get(key); + + DEBUG_REP(dmpGetUnboxedEntry(key, result)); + + if (requiresInstMethodTableArg != nullptr) + { + *requiresInstMethodTableArg = (result.B == 1); + } + + return (CORINFO_METHOD_HANDLE)(result.A); +} + void MethodContext::recGetDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE result) { if (GetDefaultEqualityComparerClass == nullptr) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h index ce62aa188d..450831d114 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -877,6 +877,13 @@ public: CORINFO_CLASS_HANDLE implClass, CORINFO_CONTEXT_HANDLE ownerType); + void recGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, + bool* requiresInstMethodTableArg, + CORINFO_METHOD_HANDLE result); + void dmpGetUnboxedEntry(DWORDLONG key, DLD value); + CORINFO_METHOD_HANDLE repGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, + bool* requiresInstMethodTableArg); + void recGetDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE result); void dmpGetDefaultEqualityComparerClass(DWORDLONG key, DWORDLONG value); CORINFO_CLASS_HANDLE repGetDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls); @@ -1269,7 +1276,7 @@ private: }; // ********************* Please keep this up-to-date to ease adding more *************** -// Highest packet number: 164 +// Highest packet number: 165 // ************************************************************************************* enum mcPackets { @@ -1384,6 +1391,7 @@ enum mcPackets Packet_GetTokenTypeAsHandle = 89, Packet_GetTypeForBox = 90, Packet_GetTypeForPrimitiveValueClass = 91, + Packet_GetUnboxedEntry = 165, // Added 10/26/17 Packet_GetUnBoxHelper = 92, Packet_GetReadyToRunHelper = 150, // Added 10/10/2014 Packet_GetReadyToRunDelegateCtorHelper = 157, // Added 3/30/2016 diff --git a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 1c7c0cbd9f..3477baca77 100644 --- a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -242,6 +242,21 @@ CORINFO_METHOD_HANDLE interceptor_ICJI::resolveVirtualMethod(CORINFO_METHOD_HAND return result; } +// Get the unboxed entry point for a method, if possible. +CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg) +{ + mc->cr->AddCall("getUnboxedEntry"); + bool localRequiresInstMethodTableArg = false; + CORINFO_METHOD_HANDLE result = + original_ICorJitInfo->getUnboxedEntry(ftn, &localRequiresInstMethodTableArg); + mc->recGetUnboxedEntry(ftn, &localRequiresInstMethodTableArg, result); + if (requiresInstMethodTableArg != nullptr) + { + *requiresInstMethodTableArg = localRequiresInstMethodTableArg; + } + return result; +} + // Given T, return the type of the default EqualityComparer<T>. // Returns null if the type can't be determined exactly. CORINFO_CLASS_HANDLE interceptor_ICJI::getDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls) diff --git a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 1e7ee24d50..a9e5761c34 100644 --- a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -163,6 +163,13 @@ CORINFO_METHOD_HANDLE interceptor_ICJI::resolveVirtualMethod(CORINFO_METHOD_HAND return original_ICorJitInfo->resolveVirtualMethod(virtualMethod, implementingClass, ownerType); } +// Get the unboxed entry point for a method, if possible. +CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg) +{ + mcs->AddCall("getUnboxedEntry"); + return original_ICorJitInfo->getUnboxedEntry(ftn, requiresInstMethodTableArg); +} + // Given T, return the type of the default EqualityComparer<T>. // Returns null if the type can't be determined exactly. CORINFO_CLASS_HANDLE interceptor_ICJI::getDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls) diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index bf3d6483d3..d7ca029fae 100644 --- a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -141,6 +141,12 @@ void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative); } +// Get the unboxed entry point for a method, if possible. +CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg) +{ + return original_ICorJitInfo->getUnboxedEntry(ftn, requiresInstMethodTableArg); +} + // 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, diff --git a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp index c53c77942a..e8f86cedbd 100644 --- a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -185,6 +185,15 @@ CORINFO_METHOD_HANDLE MyICJI::resolveVirtualMethod(CORINFO_METHOD_HANDLE virtua return result; } +// Get the unboxed entry point for a method, if possible. +CORINFO_METHOD_HANDLE MyICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg) +{ + jitInstance->mc->cr->AddCall("getUnboxedEntry"); + CORINFO_METHOD_HANDLE result = + jitInstance->mc->repGetUnboxedEntry(ftn, requiresInstMethodTableArg); + return result; +} + // Given T, return the type of the default EqualityComparer<T>. // Returns null if the type can't be determined exactly. CORINFO_CLASS_HANDLE MyICJI::getDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls) |