-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Make JIT<->EE printing methods consistent and support nested classes when printing class names #76505
Conversation
* Switch JIT to use appendClassName instead of getClassNameFromMetadata. This way it supports enclosing classes too when printing class names. * Switch appendClassName to UTF8 * Switch SIMD type recognition to use getTypeInstantiationArgument and getClassNameFromMetadata, to use of appendClassName (and depending on how it formats instantiations) * Add TypeString::FormatNoInst to avoid formatting instantiations, and use this for appendClassName
* Remove getClassName from JIT-EE interface * Remove TypeString.cs in favor of JitTypeNameFormatter that does exactly what we need * Bump JIT-EE GUID
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue Details
|
src/coreclr/jit/simd.cpp
Outdated
{ | ||
size = getSIMDVectorRegisterByteLength(); | ||
CORINFO_CLASS_HANDLE typeArgHnd = info.compCompHnd->getTypeInstantiationArgument(typeHnd, 0); | ||
simdBaseJitType = info.compCompHnd->asCorInfoType(typeArgHnd); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
asCorInfoType
Will the case of Vector<MyEnum>
be rejected properly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I probably need getTypeForPrimitiveNumericClass
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, I can see that the code below for hw intrinsics is doing exactly this but with getTypeForPrimitiveNumericClass
, so looks like that's definitely the way to go.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/OutputInfoBuilder.cs
Outdated
Show resolved
Hide resolved
Apparently caller expects the size to be right even for unsupported SIMD types.
src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj
Outdated
Show resolved
Hide resolved
Test failing with:
|
Yep, I'm looking into it. The other failure looks like #48798. |
It's very odd that my PR has failed twice with the #48798 symptom now, and that issue has no other failures. I'll try to see if I can repro this tomorrow. |
* Avoid multiple calls into EE in common case of short strings * Remove StringPrinter::AllocToPrint complexity in face of above * Optimize appendClassName on EE side with inlined implementation of what we need from TypeString that avoids multiple roundtrips in and out of UTF8. Also copy resulting string directly into final buffer. * Revert TypeString::FormatNoInst
|
||
printf("// ProcessName - '%s'\n", mc->cr->repProcessName()); | ||
printf(".assembly extern mscorlib{}\n"); | ||
printf(".assembly %s{}\n", moduleName); | ||
printf(".assembly dumped_asm\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This "scope name" was not actually the module name.
vfprintf(jitstdout, fmt, vl); | ||
va_end(vl); | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was part of a #else
of some #ifdef
I ended up removing, so I've moved it here.
static const char* s_jitHelperNames[CORINFO_HELP_COUNT] = { | ||
#define JITHELPER(code, pfnHelper, sig) #code, | ||
#define DYNAMICJITHELPER(code, pfnHelper, sig) #code, | ||
#include "jithelpers.h" | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was defined in ee_il_dll.cpp before. I've moved most of this printing into eeinterface.cpp.
It was also conditionally defined, but one of the conditions was FEATURE_SIMD
which is included for most of our targets (I think arm32 is the big exception). It seems reasonable to me to have the table unconditionally and remove the JIT-EE function.
auto disp = [&]() { | ||
char buffer[256]; | ||
printf(" %s", eeGetFieldName(tree->AsField()->gtFldHnd, true, buffer, sizeof(buffer))); | ||
}; | ||
disp(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just avoiding bloating the stack frame here, since gtDispTree
is recursive (well, it is left up to the C++ compiler's inlining).
assert(!strcmp(info.compCompHnd->getFieldName(hasValueFldHnd, nullptr), | ||
"hasValue")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could print this (or better yet, introduce getFieldNameFromMetadata
), but I don't think it's worth the effort to have the assert.
cc @dotnet/jit-contrib for the JIT/SPMI parts, @jkotas for the other parts I'm going to wait with merging this until one of the other JIT-EE changes in the pipeline go in this week. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VM/AOT parts LGTM
src/coreclr/inc/corinfo.h
Outdated
@@ -2282,7 +2282,7 @@ class ICorStaticInfo | |||
// from that first attempt was not big enough. | |||
// | |||
// Return Value: | |||
// Bytes written to the given buffer, the range is [0..bufferSize) | |||
// Bytes written to the given buffer excluding the null terminator. The range is [0..bufferSize). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be useful to note in the comment above that bufferSize
is in bytes, and *pRequiredBufferSize
is in bytes (if pRequiredBufferSize
is non-nullptr).
Can buffer
be nullptr
if bufferSize == 0
? This would be the one case where buffer
can't be null terminated, of course, and where the documented return value range [0..0) makes no sense.
Can *pRequiredBufferSize == 0
? Since it needs to include space for a null terminator, I presume it needs to be at least 1.
Can *pRequiredBufferSize == 1
? That is, only a null terminator, and no text?
If bufferSize > 0
, and the return value is < bufferSize - 1
, are we guaranteed that the entire string is written (i.e., there is no truncation)? Does this imply return value == *pRequiredBufferSize - 1
? It would be useful to document these conditions.
What happens if handle
is illegal? Crash? Null-terminated buffer
(if bufferSize > 0
)?
Presumably you can do:
size_t actualSize;
size_t sz = printObjectDescription(h, nullptr, 0, &actualSize);
assert(sz == 0);
assert(actualSize > 0);
char* buffer = new char[actualSize];
sz = printObjectDescription(h, buffer, actualSize, &actualSize);
assert(sz == actualSize - 1);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please take a look at the extra docs I've added in the latest commits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
appendClassName
/getClassName
,getFieldName
andgetMethodName
into respectivelyprintClassName
,printFieldName
andprintMethodName
that all are consistent withprintObjectDescription
in buffer handling, and all use UTF8printClassName
to support nested classes, fixing the handling of these in the JIT (in particular for method sets)printClassName
needs to be consistent with the VMCORINFO_METHOD_HANDLE
(eeMarkNativeTarget
and co.). This was unused before.CEEInfo::getHelperName
. We were keeping a list of this in the JIT anyway underFEATURE_SIMD
, which is defined practically everywhere.includeNamespaces
in JIT printing that was always passed astrue
hackishX
names on missing SPMI data into<unknown X>
instead, e.g.<unknown method>
The change does complicate the JIT side slightly since the JIT owns all the buffers now. I have added a
buffer
argument to the various JIT helper methods (e.g.eeGetFieldName
) that ensures we don't unnecessarily allocate memory in common short cases when printing these, so there are a few additional parameters passed, but in general I don't think it looks too bad. In a few recursive functions I have introduced a small lambda to avoid bloating the frame size by a lot (assuming it doesn't just get inlined).I personally prefer the consistency and flexibility over the slight increase in complexity.