Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Optimize "constant_string".Length #1378

Merged
merged 23 commits into from
Feb 14, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,10 @@ BOOL isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
);

int getStringLength(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
);

BOOL shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope);

/**********************************************************************************/
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/ToolBox/superpmi/superpmi-shared/lwmlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ LWM(IsInstantiationOfVerifiedGeneric, DWORDLONG, DWORD)
LWM(IsSDArray, DWORDLONG, DWORD)
LWM(IsStructRequiringStackAllocRetBuf, DWORDLONG, DWORD)
LWM(IsValidStringRef, DLD, DWORD)
LWM(GetStringLength, DLD, DWORD)
LWM(IsValidToken, DLD, DWORD)
LWM(IsValueClass, DWORDLONG, DWORD)
LWM(IsWriteBarrierHelperRequired, DWORDLONG, DWORD)
Expand Down
33 changes: 33 additions & 0 deletions src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4606,6 +4606,39 @@ BOOL MethodContext::repIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned m
return value;
}

void MethodContext::recGetStringLength(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int result)
{
if (GetStringLength == nullptr)
GetStringLength = new LightWeightMap<DLD, DWORD>();

DLD key;
ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
// out padding too

key.A = (DWORDLONG)module;
key.B = (DWORD)metaTOK;

GetStringLength->Add(key, (DWORD)result);
}

void MethodContext::dmpGetStringLength(DLD key, DWORD value)
{
printf("GetStringLength key mod-%016llX tok-%08X, value res-%u", key.A, key.B, value);
}

int MethodContext::repGetStringLength(CORINFO_MODULE_HANDLE module, unsigned metaTOK)
{
DLD key;
ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
// out padding too

key.A = (DWORDLONG)module;
key.B = (DWORD)metaTOK;

int value = (int)GetStringLength->Get(key);
return value;
}

void MethodContext::recGetHelperName(CorInfoHelpFunc funcNum, const char* result)
{
if (GetHelperName == nullptr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,10 @@ class MethodContext
void dmpIsValidStringRef(DLD key, DWORD value);
BOOL repIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK);

void recGetStringLength(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int result);
void dmpGetStringLength(DLD key, DWORD value);
int repGetStringLength(CORINFO_MODULE_HANDLE module, unsigned metaTOK);

void recGetHelperName(CorInfoHelpFunc funcNum, const char* result);
void dmpGetHelperName(DWORD key, DWORD value);
const char* repGetHelperName(CorInfoHelpFunc funcNum);
Expand Down Expand Up @@ -1352,7 +1356,7 @@ class MethodContext
};

// ********************* Please keep this up-to-date to ease adding more ***************
// Highest packet number: 174
// Highest packet number: 175
// *************************************************************************************
enum mcPackets
{
Expand Down Expand Up @@ -1493,6 +1497,7 @@ enum mcPackets
Packet_IsSDArray = 101,
Packet_IsStructRequiringStackAllocRetBuf = 102,
Packet_IsValidStringRef = 103,
Packet_GetStringLength = 175, // Added 1/7/2020
Retired6 = 104,
Packet_IsValidToken = 144, // Added 7/19/2013 - adjusted members to proper types
Packet_IsValueClass = 105,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,16 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return temp;
}

int interceptor_ICJI::getStringLength(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
)
{
mc->cr->AddCall("getStringLength");
int temp = original_ICorJitInfo->getStringLength(module, metaTOK);
mc->recGetStringLength(module, metaTOK, temp);
return temp;
}

BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
mc->cr->AddCall("shouldEnforceCallvirtRestriction");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,14 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return original_ICorJitInfo->isValidStringRef(module, metaTOK);
}

int interceptor_ICJI::getStringLength(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
)
{
mcs->AddCall("getStringLength");
return original_ICorJitInfo->getStringLength(module, metaTOK);
}

BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
mcs->AddCall("shouldEnforceCallvirtRestriction");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,13 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return original_ICorJitInfo->isValidStringRef(module, metaTOK);
}

int interceptor_ICJI::getStringLength(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
)
{
return original_ICorJitInfo->getStringLength(module, metaTOK);
}

BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
return original_ICorJitInfo->shouldEnforceCallvirtRestriction(scope);
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,14 @@ BOOL MyICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return jitInstance->mc->repIsValidStringRef(module, metaTOK);
}

int MyICJI::getStringLength(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
)
{
jitInstance->mc->cr->AddCall("getStringLength");
return jitInstance->mc->repGetStringLength(module, metaTOK);
}

BOOL MyICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
jitInstance->mc->cr->AddCall("shouldEnforceCallvirtRestriction");
Expand Down
15 changes: 10 additions & 5 deletions src/coreclr/src/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,11 @@ TODO: Talk about initializing strutures before use
#endif
#endif

SELECTANY const GUID JITEEVersionIdentifier = { /* abcf830c-56d1-4b33-a8ec-5063bb5495f1 */
0xabcf830c,
0x56d1,
0x4b33,
{0xa8, 0xec, 0x50, 0x63, 0xbb, 0x54, 0x95, 0xf1}
SELECTANY const GUID JITEEVersionIdentifier = { /* 13028353-152c-4886-b05b-fa76ee8169cf */
0x13028353,
0x152c,
0x4886,
{0xb0, 0x5b, 0xfa, 0x76, 0xee, 0x81, 0x69, 0xcf}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -2307,6 +2307,11 @@ class ICorStaticInfo
unsigned metaTOK /* IN */
) = 0;

virtual int getStringLength (
CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
) = 0;

virtual BOOL shouldEnforceCallvirtRestriction(
CORINFO_MODULE_HANDLE scope
) = 0;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/jit/ICorJitInfo_API_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ DEF_CLR_API(getTokenTypeAsHandle)
DEF_CLR_API(canSkipVerification)
DEF_CLR_API(isValidToken)
DEF_CLR_API(isValidStringRef)
DEF_CLR_API(getStringLength)
DEF_CLR_API(shouldEnforceCallvirtRestriction)
DEF_CLR_API(asCorInfoType)
DEF_CLR_API(getClassName)
Expand Down
10 changes: 10 additions & 0 deletions src/coreclr/src/jit/ICorJitInfo_API_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,16 @@ BOOL WrapICorJitInfo::isValidStringRef(
return temp;
}

int WrapICorJitInfo::getStringLength(
CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */)
{
API_ENTER(getStringLength);
int temp = wrapHnd->getStringLength(module, metaTOK);
API_LEAVE(getStringLength);
return temp;
}

BOOL WrapICorJitInfo::shouldEnforceCallvirtRestriction(
CORINFO_MODULE_HANDLE scope)
{
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/src/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3632,6 +3632,18 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
op1 = impPopStack().val;
if (opts.OptimizationEnabled())
{
if (op1->OperIs(GT_CNS_STR))
{
// Optimize `ldstr + String::get_Length()` to CNS_INT
// e.g. "Hello".Length => 5
int len = info.compCompHnd->getStringLength(
op1->AsStrCon()->gtScpHnd, op1->AsStrCon()->gtSconCPX);
if (len >= 0)
{
retNode = gtNewIconNode(len);
break;
}
}
GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen);
op1 = arrLen;
}
Expand Down
23 changes: 21 additions & 2 deletions src/coreclr/src/tools/Common/JitInterface/CorInfoBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ unsafe partial class CorInfoImpl
delegate uint __getExpectedTargetArchitecture(IntPtr _this, IntPtr* ppException);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate uint __getJitFlags(IntPtr _this, IntPtr* ppException, ref CORJIT_FLAGS flags, uint sizeInBytes);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate int __getStringLength(IntPtr _this, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK);

static uint _getMethodAttribs(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftn)
{
Expand Down Expand Up @@ -2830,11 +2832,25 @@ static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, ref CORJIT_FLAG
}
}

static int _getStringLength(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK)
{
var _this = GetThis(thisHandle);
try
{
return _this.getStringLength(module, metaTOK);
}
catch (Exception ex)
{
*ppException = _this.AllocException(ex);
return default(int);
}
}


static IntPtr GetUnmanagedCallbacks(out Object keepAlive)
{
IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 179);
Object[] delegates = new Object[179];
IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 180);
Object[] delegates = new Object[180];

var d0 = new __getMethodAttribs(_getMethodAttribs);
callbacks[0] = Marshal.GetFunctionPointerForDelegate(d0);
Expand Down Expand Up @@ -3373,6 +3389,9 @@ static IntPtr GetUnmanagedCallbacks(out Object keepAlive)
var d178 = new __getJitFlags(_getJitFlags);
callbacks[178] = Marshal.GetFunctionPointerForDelegate(d178);
delegates[178] = d178;
var d179 = new __getStringLength(_getStringLength);
callbacks[179] = Marshal.GetFunctionPointerForDelegate(d179);
delegates[179] = d179;

keepAlive = delegates;
return (IntPtr)callbacks;
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,8 @@ private bool isValidToken(CORINFO_MODULE_STRUCT_* module, uint metaTOK)
{ throw new NotImplementedException("isValidToken"); }
private bool isValidStringRef(CORINFO_MODULE_STRUCT_* module, uint metaTOK)
{ throw new NotImplementedException("isValidStringRef"); }
private int getStringLength(CORINFO_MODULE_STRUCT_* module, uint metaTOK)
{ throw new NotImplementedException("getStringLength"); }
private bool shouldEnforceCallvirtRestriction(CORINFO_MODULE_STRUCT_* scope)
{ throw new NotImplementedException("shouldEnforceCallvirtRestriction"); }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,4 @@ FUNCTIONS
void getModuleNativeEntryPointRange(void** pStart, void** pEnd)
DWORD getExpectedTargetArchitecture()
DWORD getJitFlags(CORJIT_FLAGS* flags, DWORD sizeInBytes)
int getStringLength(CORINFO_MODULE_HANDLE module, unsigned metaTOK)
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
cd /d %~dp0
dotnet run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\jitinterface\jitinterface.h
dotnet run -- ThunkInput.txt ..\CorInfoBase.cs ..\..\..\crossgen2\jitinterface\jitinterface.h
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
cd "$(dirname ${BASH_SOURCE[0]})"
dotnet run -- ThunkInput.txt ../CorInfoBase.cs ../../../jitinterface/jitinterface.h
dotnet run -- ThunkInput.txt ../CorInfoBase.cs ../../../crossgen2/jitinterface/jitinterface.h
10 changes: 10 additions & 0 deletions src/coreclr/src/tools/crossgen2/jitinterface/jitinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ struct JitInterfaceCallbacks
void (* getModuleNativeEntryPointRange)(void * thisHandle, CorInfoException** ppException, void** pStart, void** pEnd);
unsigned int (* getExpectedTargetArchitecture)(void * thisHandle, CorInfoException** ppException);
unsigned int (* getJitFlags)(void * thisHandle, CorInfoException** ppException, void* flags, unsigned int sizeInBytes);
int (* getStringLength)(void * thisHandle, CorInfoException** ppException, void* module, unsigned metaTOK);

};

Expand Down Expand Up @@ -1729,4 +1730,13 @@ class JitInterfaceWrapper
return _ret;
}

virtual int getStringLength(void* module, unsigned metaTOK)
{
CorInfoException* pException = nullptr;
int _ret = _callbacks->getStringLength(_thisHandle, &pException, module, metaTOK);
if (pException != nullptr)
throw pException;
return _ret;
}

};
10 changes: 5 additions & 5 deletions src/coreclr/src/tools/crossgen2/jitinterface/jitwrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ class CORJIT_FLAGS
uint64_t corJitFlags;
};

static const GUID JITEEVersionIdentifier = { /* abcf830c-56d1-4b33-a8ec-5063bb5495f1 */
0xabcf830c,
0x56d1,
0x4b33,
{0xa8, 0xec, 0x50, 0x63, 0xbb, 0x54, 0x95, 0xf1}
static const GUID JITEEVersionIdentifier = { /* 13028353-152c-4886-b05b-fa76ee8169cf */
0x13028353,
0x152c,
0x4886,
{0xb0, 0x5b, 0xfa, 0x76, 0xee, 0x81, 0x69, 0xcf}
};

class Jit
Expand Down
10 changes: 10 additions & 0 deletions src/coreclr/src/vm/dynamicmethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,16 @@ LCGMethodResolver::IsValidStringRef(mdToken metaTok)
return GetStringLiteral(metaTok) != NULL;
}

int
LCGMethodResolver::GetStringLength(mdToken metaTok)
{
STANDARD_VM_CONTRACT;

GCX_COOP();

return GetStringLiteral(metaTok)->GetStringLength();
}

//---------------------------------------------------------------------------------------
//
STRINGREF
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/src/vm/dynamicmethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class DynamicResolver
// jit interface api
virtual OBJECTHANDLE ConstructStringLiteral(mdToken metaTok) = 0;
virtual BOOL IsValidStringRef(mdToken metaTok) = 0;
virtual int GetStringLength(mdToken metaTok) = 0;
virtual void ResolveToken(mdToken token, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD) = 0;
virtual SigPointer ResolveSignature(mdToken token) = 0;
virtual SigPointer ResolveSignatureForVarArg(mdToken token) = 0;
Expand Down Expand Up @@ -122,6 +123,7 @@ class LCGMethodResolver : public DynamicResolver

OBJECTHANDLE ConstructStringLiteral(mdToken metaTok);
BOOL IsValidStringRef(mdToken metaTok);
int GetStringLength(mdToken metaTok);
void ResolveToken(mdToken token, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD);
SigPointer ResolveSignature(mdToken token);
SigPointer ResolveSignatureForVarArg(mdToken token);
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/src/vm/ilstubresolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ BOOL ILStubResolver::IsValidStringRef(mdToken metaTok)
return FALSE;
}

int ILStubResolver::GetStringLength(mdToken metaTok)
{
STANDARD_VM_CONTRACT;
_ASSERTE(FALSE);
return -1;
}

void ILStubResolver::ResolveToken(mdToken token, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD)
{
STANDARD_VM_CONTRACT;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/ilstubresolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ILStubResolver : DynamicResolver

OBJECTHANDLE ConstructStringLiteral(mdToken metaTok);
BOOL IsValidStringRef(mdToken metaTok);
int GetStringLength(mdToken metaTok);
void ResolveToken(mdToken token, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD);
SigPointer ResolveSignature(mdToken token);
SigPointer ResolveSignatureForVarArg(mdToken token);
Expand Down
Loading