未验证 提交 2f56533a 编写于 作者: B Bruce Forstall 提交者: GitHub

Add struct info to JitDump for INDEX and IND nodes (#67135)

Also, shorten struct type name display. Use the `appendClassName`
API to construct a smaller class name, without the full assembly info.
上级 83e2529d
......@@ -8470,6 +8470,7 @@ public:
#if defined(DEBUG)
const WCHAR* eeGetCPString(size_t stringHandle);
const char16_t* eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd);
#endif
const char* eeGetClassName(CORINFO_CLASS_HANDLE clsHnd);
......
......@@ -1370,6 +1370,7 @@ struct FilterSuperPMIExceptionsParam_ee_il
CORINFO_CLASS_HANDLE clazz;
const char** classNamePtr;
const char* fieldOrMethodOrClassNamePtr;
char16_t* classNameWidePtr;
EXCEPTION_POINTERS exceptionPointers;
};
......@@ -1480,6 +1481,70 @@ const char* Compiler::eeGetClassName(CORINFO_CLASS_HANDLE clsHnd)
#ifdef DEBUG
//------------------------------------------------------------------------
// eeGetShortClassName: wraps appendClassName to provide functionality
// similar to getClassName(), but returns a class name that is shortened,
// not using full assembly info.
//
// Arguments:
// clsHnd - the class handle to get the type name of
//
// Return value:
// string class name. Note: unlike eeGetClassName/getClassName, this string is
// allocated from the JIT heap, so care should possibly be taken to avoid leaking it.
// It returns a char16_t string, since that's what appendClassName returns.
//
const char16_t* Compiler::eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd)
{
FilterSuperPMIExceptionsParam_ee_il param;
param.pThis = this;
param.pJitInfo = &info;
param.clazz = clsHnd;
bool success = eeRunWithSPMIErrorTrap<FilterSuperPMIExceptionsParam_ee_il>(
[](FilterSuperPMIExceptionsParam_ee_il* pParam) {
char16_t dummyClassName[1] = {0};
char16_t* pbuf = &dummyClassName[0];
int len = 0;
constexpr bool fNamespace = true;
constexpr bool fFullInst = false;
constexpr bool fAssembly = false;
// Warning: crossgen2 doesn't fully implement the `appendClassName` API.
// If the size passed isn't large enough to the hold the entire string, crossgen2 will copy as much
// as possible. However, the EE will assert. So we need to pass zero, get back the actual buffer size
// required, allocate that space, and call the API again to get the full string. Both EE and crossgen2
// will return the actual string size if *pnBufLen is zero.
// The resulting string is guaranteed to be null-terminated.
// Returned value is size of requested string, in characters, not including the terminating null
// character. This could be larger than the buffer size and thus larger than the number of characters
// actually copied to *pBuf (in the case of crossgen2, which doesn't assert on too-small buffers).
int cchStrLen = pParam->pJitInfo->compCompHnd->appendClassName(&pbuf, &len, pParam->clazz, fNamespace,
fFullInst, fAssembly);
size_t cchBufLen = (size_t)cchStrLen + /* null terminator */ 1;
pParam->classNameWidePtr = pParam->pThis->getAllocator(CMK_DebugOnly).allocate<char16_t>(cchBufLen);
pbuf = pParam->classNameWidePtr;
len = (int)cchBufLen;
int cchResultStrLen = pParam->pJitInfo->compCompHnd->appendClassName(&pbuf, &len, pParam->clazz, fNamespace,
fFullInst, fAssembly);
noway_assert(cchStrLen == cchResultStrLen);
noway_assert(pParam->classNameWidePtr[cchResultStrLen] == 0);
},
&param);
if (!success)
{
const char16_t substituteClassName[] = u"hackishClassName";
size_t cchLen = ArrLen(substituteClassName);
param.classNameWidePtr = getAllocator(CMK_DebugOnly).allocate<char16_t>(cchLen);
memcpy(param.classNameWidePtr, substituteClassName, cchLen * sizeof(char16_t));
}
return param.classNameWidePtr;
}
const WCHAR* Compiler::eeGetCPString(size_t strHandle)
{
#ifdef HOST_UNIX
......
......@@ -9808,6 +9808,35 @@ void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, _In_ _In_opt_
layout = varDsc->GetLayout();
}
}
else if (tree->OperIs(GT_INDEX))
{
GenTreeIndex* asInd = tree->AsIndex();
CORINFO_CLASS_HANDLE clsHnd = asInd->gtStructElemClass;
if (clsHnd != nullptr)
{
// We could create a layout with `typGetObjLayout(asInd->gtStructElemClass)` but we
// don't want to affect the layout table.
const unsigned classSize = info.compCompHnd->getClassSize(clsHnd);
const char16_t* shortClassName = eeGetShortClassName(clsHnd);
printf("<%S, %u>", shortClassName, classSize);
}
}
else if (tree->OperIsIndir())
{
ArrayInfo arrInfo;
if (TryGetArrayInfo(tree->AsIndir(), &arrInfo))
{
if (varTypeIsStruct(arrInfo.m_elemType))
{
CORINFO_CLASS_HANDLE clsHnd = arrInfo.m_elemStructType;
// We could create a layout with `typGetObjLayout(asInd->gtStructElemClass)` but we
// don't want to affect the layout table.
const unsigned classSize = info.compCompHnd->getClassSize(clsHnd);
const char16_t* shortClassName = eeGetShortClassName(clsHnd);
printf("<%S, %u>", shortClassName, classSize);
}
}
}
if (layout != nullptr)
{
......@@ -10248,11 +10277,11 @@ void Compiler::gtDispClassLayout(ClassLayout* layout, var_types type)
}
else if (varTypeIsSIMD(type))
{
printf("<%s>", layout->GetClassName());
printf("<%S>", layout->GetShortClassName());
}
else
{
printf("<%s, %u>", layout->GetClassName(), layout->GetSize());
printf("<%S, %u>", layout->GetShortClassName(), layout->GetSize());
}
}
......@@ -12154,7 +12183,7 @@ GenTree* Compiler::gtFoldTypeCompare(GenTree* tree)
if ((cls1Hnd != NO_CLASS_HANDLE) && (cls2Hnd != NO_CLASS_HANDLE))
{
JITDUMP("Asking runtime to compare %p (%s) and %p (%s) for equality\n", dspPtr(cls1Hnd),
info.compCompHnd->getClassName(cls1Hnd), dspPtr(cls2Hnd), info.compCompHnd->getClassName(cls2Hnd));
eeGetClassName(cls1Hnd), dspPtr(cls2Hnd), eeGetClassName(cls2Hnd));
TypeCompareState s = info.compCompHnd->compareTypesForEquality(cls1Hnd, cls2Hnd);
if (s != TypeCompareState::May)
......
......@@ -4094,7 +4094,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
const bool isReadOnly = (ni == NI_System_ReadOnlySpan_get_Item);
JITDUMP("\nimpIntrinsic: Expanding %sSpan<T>.get_Item, T=%s, sizeof(T)=%u\n",
isReadOnly ? "ReadOnly" : "", info.compCompHnd->getClassName(spanElemHnd), elemSize);
isReadOnly ? "ReadOnly" : "", eeGetClassName(spanElemHnd), elemSize);
GenTree* index = impPopStack().val;
GenTree* ptrToSpan = impPopStack().val;
......@@ -11505,8 +11505,8 @@ GenTree* Compiler::impOptimizeCastClassOrIsInst(GenTree* op1, CORINFO_RESOLVED_T
{
CORINFO_CLASS_HANDLE toClass = pResolvedToken->hClass;
JITDUMP("\nConsidering optimization of %s from %s%p (%s) to %p (%s)\n", isCastClass ? "castclass" : "isinst",
isExact ? "exact " : "", dspPtr(fromClass), info.compCompHnd->getClassName(fromClass), dspPtr(toClass),
info.compCompHnd->getClassName(toClass));
isExact ? "exact " : "", dspPtr(fromClass), eeGetClassName(fromClass), dspPtr(toClass),
eeGetClassName(toClass));
// Perhaps we know if the cast will succeed or fail.
TypeCompareState castResult = info.compCompHnd->compareTypesForCast(fromClass, toClass);
......@@ -21035,8 +21035,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
if (verbose || doPrint)
{
objClassNote = isExact ? " [exact]" : objClassIsFinal ? " [final]" : "";
objClassName = info.compCompHnd->getClassName(objClass);
baseClassName = info.compCompHnd->getClassName(baseClass);
objClassName = eeGetClassName(objClass);
baseClassName = eeGetClassName(baseClass);
baseMethodName = eeGetMethodName(baseMethod, nullptr);
if (verbose)
......
......@@ -334,10 +334,11 @@ ClassLayout* ClassLayout::Create(Compiler* compiler, CORINFO_CLASS_HANDLE classH
size = compiler->info.compCompHnd->getHeapClassSize(classHandle);
}
INDEBUG(const char* className = compiler->info.compCompHnd->getClassName(classHandle);)
INDEBUG(const char* className = compiler->eeGetClassName(classHandle);)
INDEBUG(const char16_t* shortClassName = compiler->eeGetShortClassName(classHandle);)
ClassLayout* layout =
new (compiler, CMK_ClassLayout) ClassLayout(classHandle, isValueClass, size DEBUGARG(className));
ClassLayout* layout = new (compiler, CMK_ClassLayout)
ClassLayout(classHandle, isValueClass, size DEBUGARG(className) DEBUGARG(shortClassName));
layout->InitializeGCPtrs(compiler);
return layout;
}
......
......@@ -38,6 +38,9 @@ class ClassLayout
// Class name as reported by ICorJitInfo::getClassName
INDEBUG(const char* m_className;)
// Shortened class name as constructed by Compiler::eeGetShortClassName()
INDEBUG(const char16_t* m_shortClassName;)
// ClassLayout instances should only be obtained via ClassLayoutTable.
friend class ClassLayoutTable;
......@@ -52,13 +55,16 @@ class ClassLayout
, m_gcPtrs(nullptr)
#ifdef DEBUG
, m_className("block")
, m_shortClassName(u"block")
#endif
{
}
static ClassLayout* Create(Compiler* compiler, CORINFO_CLASS_HANDLE classHandle);
ClassLayout(CORINFO_CLASS_HANDLE classHandle, bool isValueClass, unsigned size DEBUGARG(const char* className))
ClassLayout(CORINFO_CLASS_HANDLE classHandle,
bool isValueClass,
unsigned size DEBUGARG(const char* className) DEBUGARG(const char16_t* shortClassName))
: m_classHandle(classHandle)
, m_size(size)
, m_isValueClass(isValueClass)
......@@ -69,6 +75,7 @@ class ClassLayout
, m_gcPtrs(nullptr)
#ifdef DEBUG
, m_className(className)
, m_shortClassName(shortClassName)
#endif
{
assert(size != 0);
......@@ -88,11 +95,18 @@ public:
}
#ifdef DEBUG
const char* GetClassName() const
{
return m_className;
}
#endif
const char16_t* GetShortClassName() const
{
return m_shortClassName;
}
#endif // DEBUG
bool IsValueClass() const
{
......
......@@ -2933,8 +2933,8 @@ void Compiler::lvaSetClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool is
assert(varDsc->lvClassHnd == NO_CLASS_HANDLE);
assert(!varDsc->lvClassIsExact);
JITDUMP("\nlvaSetClass: setting class for V%02i to (%p) %s %s\n", varNum, dspPtr(clsHnd),
info.compCompHnd->getClassName(clsHnd), isExact ? " [exact]" : "");
JITDUMP("\nlvaSetClass: setting class for V%02i to (%p) %s %s\n", varNum, dspPtr(clsHnd), eeGetClassName(clsHnd),
isExact ? " [exact]" : "");
varDsc->lvClassHnd = clsHnd;
varDsc->lvClassIsExact = isExact;
......@@ -3044,9 +3044,9 @@ void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool
if (isNewClass || (isExact != varDsc->lvClassIsExact))
{
JITDUMP("\nlvaUpdateClass:%s Updating class for V%02u", shouldUpdate ? "" : " NOT", varNum);
JITDUMP(" from (%p) %s%s", dspPtr(varDsc->lvClassHnd), info.compCompHnd->getClassName(varDsc->lvClassHnd),
JITDUMP(" from (%p) %s%s", dspPtr(varDsc->lvClassHnd), eeGetClassName(varDsc->lvClassHnd),
varDsc->lvClassIsExact ? " [exact]" : "");
JITDUMP(" to (%p) %s%s\n", dspPtr(clsHnd), info.compCompHnd->getClassName(clsHnd), isExact ? " [exact]" : "");
JITDUMP(" to (%p) %s%s\n", dspPtr(clsHnd), eeGetClassName(clsHnd), isExact ? " [exact]" : "");
}
#endif // DEBUG
......
......@@ -5371,10 +5371,10 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree)
GenTree* arrRef2 = nullptr; // The second copy will be used in array address expression
GenTree* index2 = nullptr;
// If the arrRef or index expressions involves an assignment, a call or reads from global memory,
// If the arrRef or index expressions involves an assignment, a call, or reads from global memory,
// then we *must* allocate a temporary in which to "localize" those values, to ensure that the
// same values are used in the bounds check and the actual dereference.
// Also we allocate the temporary when the expresion is sufficiently complex/expensive.
// Also we allocate the temporary when the expression is sufficiently complex/expensive.
//
// Note that if the expression is a GT_FIELD, it has not yet been morphed so its true complexity is
// not exposed. Without that condition there are cases of local struct fields that were previously,
......@@ -5420,7 +5420,7 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree)
#ifdef TARGET_64BIT
// The CLI Spec allows an array to be indexed by either an int32 or a native int. In the case
// of a 64 bit architecture this means the array index can potentially be a TYP_LONG, so for this case,
// the comparison will have to be widen to 64 bits.
// the comparison will have to be widened to 64 bits.
if (index->TypeGet() == TYP_I_IMPL)
{
bndsChkType = TYP_I_IMPL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册