Skip to content
Merged
5 changes: 3 additions & 2 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2240,10 +2240,11 @@ class ICorStaticInfo

// Returns string length and content (can be null for dynamic context)
// for given metaTOK and module, length `-1` means input is incorrect
virtual const char16_t * getStringLiteral (
virtual int getStringLiteral (
CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK, /* IN */
int* length /* OUT */
char16_t* buffer, /* OUT */
int bufferSize /* IN */
) = 0;

/**********************************************************************************/
Expand Down
5 changes: 3 additions & 2 deletions src/coreclr/inc/icorjitinfoimpl_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,11 @@ bool isValidStringRef(
CORINFO_MODULE_HANDLE module,
unsigned metaTOK) override;

const char16_t* getStringLiteral(
int getStringLiteral(
CORINFO_MODULE_HANDLE module,
unsigned metaTOK,
int* length) override;
char16_t* buffer,
int bufferSize) override;

CorInfoType asCorInfoType(
CORINFO_CLASS_HANDLE cls) override;
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* 206a7aa6-9f5c-47c1-b63b-54f4cb169ee3 */
0x206a7aa6,
0x9f5c,
0x47c1,
{0xb6, 0x3b, 0x54, 0xf4, 0xcb, 0x16, 0x9e, 0xe3}
constexpr GUID JITEEVersionIdentifier = { /* b0719856-6fe6-407c-bf40-7a57e22b2382 */
0xb0719856,
0x6fe6,
0x407c,
{0xbf, 0x40, 0x7a, 0x57, 0xe2, 0x2b, 0x23, 0x82}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
7 changes: 4 additions & 3 deletions src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,14 @@ bool WrapICorJitInfo::isValidStringRef(
return temp;
}

const char16_t* WrapICorJitInfo::getStringLiteral(
int WrapICorJitInfo::getStringLiteral(
CORINFO_MODULE_HANDLE module,
unsigned metaTOK,
int* length)
char16_t* buffer,
int bufferSize)
{
API_ENTER(getStringLiteral);
const char16_t* temp = wrapHnd->getStringLiteral(module, metaTOK, length);
int temp = wrapHnd->getStringLiteral(module, metaTOK, buffer, bufferSize);
API_LEAVE(getStringLiteral);
return temp;
}
Expand Down
14 changes: 2 additions & 12 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6957,21 +6957,11 @@ GenTreeIntCon* Compiler::gtNewStringLiteralLength(GenTreeStrCon* node)
return gtNewIconNode(0);
}

int length = -1;
const char16_t* str = info.compCompHnd->getStringLiteral(node->gtScpHnd, node->gtSconCPX, &length);
int length = info.compCompHnd->getStringLiteral(node->gtScpHnd, node->gtSconCPX, nullptr, 0);
if (length >= 0)
Comment thread
jkotas marked this conversation as resolved.
{
GenTreeIntCon* iconNode = gtNewIconNode(length);

// str can be NULL for dynamic context
if (str != nullptr)
{
JITDUMP("Folded '\"%ws\".Length' to '%d'\n", str, length)
}
else
{
JITDUMP("Folded 'CNS_STR.Length' to '%d'\n", length)
}
JITDUMP("Folded 'CNS_STR.Length' to '%d'\n", length)
return iconNode;
}
return nullptr;
Expand Down
28 changes: 15 additions & 13 deletions src/coreclr/jit/importer_vectorization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#pragma hdrstop
#endif

// For now the max possible size is Vector256<ushort>.Count * 2
#define MaxPossibleUnrollSize 32

//------------------------------------------------------------------------
// importer_vectorization.cpp
//
Expand Down Expand Up @@ -145,8 +148,7 @@ static GenTreeHWIntrinsic* CreateConstVector(Compiler* comp, var_types simdType,
GenTree* Compiler::impExpandHalfConstEqualsSIMD(
GenTreeLclVar* data, WCHAR* cns, int len, int dataOffset, StringComparison cmpMode)
{
constexpr int maxPossibleLength = 32;
assert(len >= 8 && len <= maxPossibleLength);
assert(len >= 8 && len <= MaxPossibleUnrollSize);

if (!IsBaselineSimdIsaSupported())
{
Expand All @@ -170,8 +172,8 @@ GenTree* Compiler::impExpandHalfConstEqualsSIMD(
// Optimization: don't use two vectors for Length == 8 or 16
bool useSingleVector = false;

WCHAR cnsValue[maxPossibleLength] = {};
WCHAR toLowerMask[maxPossibleLength] = {};
WCHAR cnsValue[MaxPossibleUnrollSize] = {};
WCHAR toLowerMask[MaxPossibleUnrollSize] = {};

memcpy((UINT8*)cnsValue, (UINT8*)cns, len * sizeof(WCHAR));

Expand Down Expand Up @@ -678,8 +680,8 @@ GenTree* Compiler::impStringEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO
needsNullcheck = false;
}

int cnsLength = -1;
const char16_t* str = nullptr;
int cnsLength;
char16_t str[MaxPossibleUnrollSize];
if (cnsStr->IsStringEmptyField())
{
// check for fake "" first
Expand All @@ -688,13 +690,13 @@ GenTree* Compiler::impStringEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO
}
else
{
str = info.compCompHnd->getStringLiteral(cnsStr->gtScpHnd, cnsStr->gtSconCPX, &cnsLength);
if ((cnsLength < 0) || (str == nullptr))
cnsLength = info.compCompHnd->getStringLiteral(cnsStr->gtScpHnd, cnsStr->gtSconCPX, str, MaxPossibleUnrollSize);
if ((cnsLength < 0) || (cnsLength > MaxPossibleUnrollSize))
{
// We were unable to get the literal (e.g. dynamic context)
return nullptr;
}
JITDUMP("Trying to unroll String.Equals|StartsWith(op1, \"%ws\")...\n", str)
JITDUMP("Trying to unroll String.Equals|StartsWith(op1, \"cns\")...\n")
}

// Create a temp which is safe to gtClone for varStr
Expand Down Expand Up @@ -816,8 +818,8 @@ GenTree* Compiler::impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO*
spanObj = op1;
}

int cnsLength = -1;
const char16_t* str = nullptr;
int cnsLength = -1;
char16_t str[MaxPossibleUnrollSize];
if (cnsStr->IsStringEmptyField())
{
// check for fake "" first
Expand All @@ -826,8 +828,8 @@ GenTree* Compiler::impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO*
}
else
{
str = info.compCompHnd->getStringLiteral(cnsStr->gtScpHnd, cnsStr->gtSconCPX, &cnsLength);
if (cnsLength < 0 || str == nullptr)
cnsLength = info.compCompHnd->getStringLiteral(cnsStr->gtScpHnd, cnsStr->gtSconCPX, str, MaxPossibleUnrollSize);
if ((cnsLength < 0) || (cnsLength > MaxPossibleUnrollSize))
{
// We were unable to get the literal (e.g. dynamic context)
return nullptr;
Expand Down
9 changes: 5 additions & 4 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4854,10 +4854,11 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree)
const int cnsIndex = static_cast<int>(asIndex->Index()->AsIntConCommon()->IconValue());
if (cnsIndex >= 0)
{
int length;
const char16_t* str = info.compCompHnd->getStringLiteral(asIndex->Arr()->AsStrCon()->gtScpHnd,
asIndex->Arr()->AsStrCon()->gtSconCPX, &length);
if ((cnsIndex < length) && (str != nullptr))
const int maxStrSize = 1024;
char16_t str[maxStrSize];
int length = info.compCompHnd->getStringLiteral(asIndex->Arr()->AsStrCon()->gtScpHnd,
asIndex->Arr()->AsStrCon()->gtSconCPX, str, maxStrSize);
if ((cnsIndex < length))
{
GenTree* cnsCharNode = gtNewIconNode(str[cnsIndex], TYP_INT);
INDEBUG(cnsCharNode->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/tools/Common/JitInterface/CorInfoBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -525,12 +525,12 @@ static byte _isValidStringRef(IntPtr thisHandle, IntPtr* ppException, CORINFO_MO
}

[UnmanagedCallersOnly]
static char* _getStringLiteral(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK, int* length)
static int _getStringLiteral(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK, char* buffer, int bufferSize)
{
var _this = GetThis(thisHandle);
try
{
return _this.getStringLiteral(module, metaTOK, ref *length);
return _this.getStringLiteral(module, metaTOK, buffer, bufferSize);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -2604,7 +2604,7 @@ static IntPtr GetUnmanagedCallbacks()
callbacks[32] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_CLASS_STRUCT_*>)&_getTokenTypeAsHandle;
callbacks[33] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, uint, byte>)&_isValidToken;
callbacks[34] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, uint, byte>)&_isValidStringRef;
callbacks[35] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, uint, int*, char*>)&_getStringLiteral;
callbacks[35] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, uint, char*, int, int>)&_getStringLiteral;
callbacks[36] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CorInfoType>)&_asCorInfoType;
callbacks[37] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte*>)&_getClassName;
callbacks[38] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte**, byte*>)&_getClassNameFromMetadata;
Expand Down
15 changes: 11 additions & 4 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1875,12 +1875,19 @@ private bool isValidToken(CORINFO_MODULE_STRUCT_* module, uint metaTOK)
private bool isValidStringRef(CORINFO_MODULE_STRUCT_* module, uint metaTOK)
{ throw new NotImplementedException("isValidStringRef"); }

private char* getStringLiteral(CORINFO_MODULE_STRUCT_* module, uint metaTOK, ref int length)
private int getStringLiteral(CORINFO_MODULE_STRUCT_* module, uint metaTOK, char* buffer, int size)
{
Debug.Assert(size >= 0);

MethodILScope methodIL = HandleToObject(module);
string s = (string)methodIL.GetObject((int)metaTOK);
length = (int)s.Length;
return (char*)GetPin(s);
string str = (string)methodIL.GetObject((int)metaTOK);

if (buffer != null)
{
// Copy str's content to buffer
str.AsSpan(0, Math.Min(size, str.Length)).CopyTo(new Span<char>(buffer, size));
}
return str.Length;
}

private CorInfoType asCorInfoType(CORINFO_CLASS_STRUCT_* cls)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ FUNCTIONS
CORINFO_CLASS_HANDLE getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken)
bool isValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK)
bool isValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK)
const char16_t * getStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length)
int getStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize)
CorInfoType asCorInfoType(CORINFO_CLASS_HANDLE cls)
const char* getClassName(CORINFO_CLASS_HANDLE cls)
const char* getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char **namespaceName)
Expand Down
9 changes: 5 additions & 4 deletions src/coreclr/tools/aot/jitinterface/jitinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct JitInterfaceCallbacks
CORINFO_CLASS_HANDLE (* getTokenTypeAsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken);
bool (* isValidToken)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK);
bool (* isValidStringRef)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK);
const char16_t* (* getStringLiteral)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length);
int (* getStringLiteral)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize);
CorInfoType (* asCorInfoType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls);
const char* (* getClassName)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls);
const char* (* getClassNameFromMetadata)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, const char** namespaceName);
Expand Down Expand Up @@ -540,13 +540,14 @@ class JitInterfaceWrapper : public ICorJitInfo
return temp;
}

virtual const char16_t* getStringLiteral(
virtual int getStringLiteral(
CORINFO_MODULE_HANDLE module,
unsigned metaTOK,
int* length)
char16_t* buffer,
int bufferSize)
{
CorInfoExceptionClass* pException = nullptr;
const char16_t* temp = _callbacks->getStringLiteral(_thisHandle, &pException, module, metaTOK, length);
int temp = _callbacks->getStringLiteral(_thisHandle, &pException, module, metaTOK, buffer, bufferSize);
if (pException != nullptr) throw pException;
return temp;
}
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ LWM(IsFieldStatic, DWORDLONG, DWORD)
LWM(IsIntrinsicType, DWORDLONG, DWORD)
LWM(IsSDArray, DWORDLONG, DWORD)
LWM(IsValidStringRef, DLD, DWORD)
LWM(GetStringLiteral, DLD, DD)
LWM(GetStringLiteral, DLDD, DD)
LWM(IsValidToken, DLD, DWORD)
LWM(IsValueClass, DWORDLONG, DWORD)
LWM(MergeClasses, DLDL, DWORDLONG)
Expand Down
36 changes: 18 additions & 18 deletions src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4765,20 +4765,20 @@ bool MethodContext::repIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned m
return value != 0;
}


void MethodContext::recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int length, const char16_t* result)
void MethodContext::recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int length)
{
if (GetStringLiteral == nullptr)
GetStringLiteral = new LightWeightMap<DLD, DD>();
GetStringLiteral = new LightWeightMap<DLDD, DD>();

DLD key;
DLDD key;
ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding
key.A = CastHandle(module);
key.B = (DWORD)metaTOK;
key.C = (DWORD)bufferSize;

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

DD value;
value.A = (DWORD)length;
Expand All @@ -4788,39 +4788,39 @@ void MethodContext::recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned m
DEBUG_REC(dmpGetStringLiteral(key, value));
}

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

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

DLD key;
DLDD key;
ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding
key.A = CastHandle(module);
key.B = (DWORD)metaTOK;
key.C = (DWORD)bufferSize;

int itemIndex = GetStringLiteral->GetIndex(key);
if (itemIndex < 0)
{
*length = -1;
return nullptr;
return -1;
}
else
{
DD value = GetStringLiteral->Get(key);
DEBUG_REP(dmpGetStringLiteral(key, value));

*length = (int)value.A;
return (const char16_t*)GetStringLiteral->GetBuffer(value.B);
if (buffer != nullptr)
{
memcpy(buffer, GetStringLiteral->GetBuffer(value.B), bufferSize * sizeof(char16_t));
}
return (int)value.A;
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -600,9 +600,9 @@ 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, const char16_t* result);
void dmpGetStringLiteral(DLD key, DD value);
const char16_t* repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length);
void recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int length);
void dmpGetStringLiteral(DLDD key, DD value);
int repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize);

void recGetHelperName(CorInfoHelpFunc funcNum, const char* result);
void dmpGetHelperName(DWORD key, DWORD value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,14 +434,15 @@ bool interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
return temp;
}

const char16_t* interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK, /* IN */
int* length /* OUT */
)
int interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */
unsigned metaTOK, /* IN */
char16_t* buffer, /* OUT */
int bufferSize /* IN */
)
{
mc->cr->AddCall("getStringLiteral");
const char16_t* temp = original_ICorJitInfo->getStringLiteral(module, metaTOK, length);
mc->recGetStringLiteral(module, metaTOK, *length, temp);
int temp = original_ICorJitInfo->getStringLiteral(module, metaTOK, buffer, bufferSize);
mc->recGetStringLiteral(module, metaTOK, buffer, bufferSize, temp);
return temp;
}

Expand Down
Loading