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 all 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,11 @@ BOOL isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK /* IN */
);

LPCWSTR getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK, /* IN */
int* length /* OUT */
);

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(GetStringLiteral, DLD, DD)
LWM(IsValidToken, DLD, DWORD)
LWM(IsValueClass, DWORDLONG, DWORD)
LWM(IsWriteBarrierHelperRequired, DWORDLONG, DWORD)
Expand Down
59 changes: 59 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,65 @@ BOOL MethodContext::repIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned m
return value;
}


void MethodContext::recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int length, LPCWSTR result)
{
if (GetStringLiteral == nullptr)
GetStringLiteral = new LightWeightMap<DLD, DD>();

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;

DWORD strBuf = (DWORD)-1;
if (result != nullptr)
strBuf = (DWORD)GetStringLiteral->AddBuffer((unsigned char*)result, (unsigned int)((wcslen(result) * 2) + 2));

DD value;
value.A = (DWORD)length;
value.B = (DWORD)strBuf;

GetStringLiteral->Add(key, value);
}

void MethodContext::dmpGetStringLiteral(DLD key, DD value)
{
printf("GetStringLiteral key mod-%016llX tok-%08X, result-%s, len-%u", key.A, key.B,
GetStringLiteral->GetBuffer(value.B), value.A);
}

LPCWSTR MethodContext::repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length)
{
if (GetStringLiteral == nullptr)
{
*length = -1;
return nullptr;
}

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 itemIndex = GetStringLiteral->GetIndex(key);
if (itemIndex < 0)
{
*length = -1;
return nullptr;
}
else
{
DD result = GetStringLiteral->Get(key);
*length = (int)result.A;
return (LPCWSTR)GetStringLiteral->GetBuffer(itemIndex);
}
}

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 recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int length, LPCWSTR result);
void dmpGetStringLiteral(DLD key, DD value);
LPCWSTR repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length);

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_GetStringLiteral = 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,17 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return temp;
}

LPCWSTR interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK, /* IN */
int* length /* OUT */
)
{
mc->cr->AddCall("getStringLiteral");
LPCWSTR temp = original_ICorJitInfo->getStringLiteral(module, metaTOK, length);
mc->recGetStringLiteral(module, metaTOK, *length, 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,15 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return original_ICorJitInfo->isValidStringRef(module, metaTOK);
}

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

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,14 @@ BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return original_ICorJitInfo->isValidStringRef(module, metaTOK);
}

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

BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
return original_ICorJitInfo->shouldEnforceCallvirtRestriction(scope);
Expand Down
9 changes: 9 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,15 @@ BOOL MyICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return jitInstance->mc->repIsValidStringRef(module, metaTOK);
}

LPCWSTR MyICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK, /* IN */
int* length /* OUT */
)
{
jitInstance->mc->cr->AddCall("getStringLiteral");
return jitInstance->mc->repGetStringLiteral(module, metaTOK, length);
}

BOOL MyICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
{
jitInstance->mc->cr->AddCall("shouldEnforceCallvirtRestriction");
Expand Down
18 changes: 13 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,14 @@ class ICorStaticInfo
unsigned metaTOK /* IN */
) = 0;

// Returns string length and content (can be null for dynamic context)
// for given metaTOK and module, length `-1` means input is incorrect
virtual LPCWSTR getStringLiteral (
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK, /* IN */
int* length /* OUT */
) = 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(getStringLiteral)
DEF_CLR_API(shouldEnforceCallvirtRestriction)
DEF_CLR_API(asCorInfoType)
DEF_CLR_API(getClassName)
Expand Down
11 changes: 11 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,17 @@ BOOL WrapICorJitInfo::isValidStringRef(
return temp;
}

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

BOOL WrapICorJitInfo::shouldEnforceCallvirtRestriction(
CORINFO_MODULE_HANDLE scope)
{
Expand Down
21 changes: 21 additions & 0 deletions src/coreclr/src/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3632,6 +3632,27 @@ 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 length = -1;
LPCWSTR str = info.compCompHnd->getStringLiteral(op1->AsStrCon()->gtScpHnd,
op1->AsStrCon()->gtSconCPX, &length);
if (length >= 0)
{
retNode = gtNewIconNode(length);
if (str != nullptr) // can be NULL for dynamic context
{
JITDUMP("Optimizing '\"%ws\".Length' to just '%d'\n", str, length);
}
else
{
JITDUMP("Optimizing 'CNS_STR.Length' to just '%d'\n", length);
}
break;
}
}
GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, op1, OFFSETOF__CORINFO_String__stringLen, compCurBB);
op1 = arrLen;
}
Expand Down
Loading