-
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
Gc arrays #111686
base: main
Are you sure you want to change the base?
Gc arrays #111686
Conversation
These flags are strictly optimizations. Having them required to be set for certain indirs based on context of the operand introduces IR invariants that are annoying to work with since it suddenly becomes necessary for all transformations to consider "did we just introduce this IR shape?". Instead, handle these patterns during morph as the optimization it is and remove the strict flags checking from `fgDebugCheckFlags`.
…-array-stack-alloc
Extend array stack allocation to arrays with GC typed elements. Implement an array ClassLayout. This currently naively duplicates the element layout for each element.
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
bool IsArrayLayout() const | ||
{ | ||
return m_elementCount > 0; | ||
} |
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 was hoping we would not end up with another "layout kind", instead adding full support for custom layouts and removing block layouts. It would benefit more places than just array stack allocation.
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 say more about what you had in mind? Some kind of ability to compose layouts from other layouts, including repeating elements?
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.
Today we have CreateObjLayout(CORINFO_CLASS_HANDLE)
and CreateBlkLayout(unsigned size)
. What I was thinking is to delete block layouts in favor of a CreateCustomLayout(unsigned size, CorInfoGCType* slotGCTypes)
, potentially with a way to set the significant segments (non-padding) as well. Block layouts would be represented as CreateCustomLayout(size, nullptr)
. Array layouts would be represented via repeating the GC pointer types and padding of another layout. Box layouts would be created by adding an extra non-pointer at the beginning of another layout (removing the need for getTypeForBoxOnStack
). Physical promotion would also benefit as it could start representing remainders with GC pointers, so it would need to copy less in some cases.
The custom layouts could almost subsume even object layouts, however we do have a few cases left where we need to get the CORINFO_CLASS_HANDLE
out of a layout. If we got rid of those we could unify everything on the custom layouts.
I think the main work would be in going around and replacing the ClassLayout::IsBlockLayout
checks with either "is custom layout" (no class handle) or "has GC pointers" checks. Of course the devil might be in the details...
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 certainly also introduce some ClassLayoutBuilder
class to allow easily composing a new custom class layout from various building blocks (like repeating a layout some number of times)
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.
One hangup in moving to a more general construction is the hashing scheme -- without a class handle as a convenient key, it seems like we may need to compute a full layout in order to realize we have created a duplicate, at which point the value of duplicate detection is minimal, as we've likely already burned the memory.
For block layouts this is not a concern, since their only interesting property is their size, but once there are gc slots scattered about...
Perhaps it's rare to create duplicate custom layouts so this is a non-problem (though this PR currently relies on it since it was simple to do). Or we perhaps we just don't worry about it and waste some memory representing duplicates?
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.
Perhaps it's rare to create duplicate custom layouts so this is a non-problem (though this PR currently relies on it since it was simple to do). Or we perhaps we just don't worry about it and waste some memory representing duplicates?
It sounds ok to me to waste a bit of memory. ClassLayout
itself already does that -- it could represent the GC pointers array using much less memory than it is doing now, since each element requires only 2 bits. With a ClassLayoutBuilder
using small-size optimization most layouts probably wouldn't require any dynamic allocation if they hit the cache for custom layouts.
Not sure I would worry about it though... We probably aren't going to be creating that many custom layouts, and when we do it's because some optimization is triggering anyway.
I'm not sure that the caching is as much about saving memory as it is about having a canonical index/ID for each layout. See this comment:
runtime/src/coreclr/jit/layout.cpp
Lines 15 to 19 in c74440f
// Each layout is assigned a number, starting with TYP_UNKNOWN + 1. This way one could use a single | |
// unsigned value to represent the notion of type - values below TYP_UNKNOWN are var_types and values | |
// above it are struct layouts. | |
static constexpr unsigned ZeroSizedBlockLayoutNum = TYP_UNKNOWN + 1; | |
static constexpr unsigned FirstLayoutNum = TYP_UNKNOWN + 2; |
We have never really used this capability, though.
SPMI has too many missed contexts, also this depends on the base array PR... need to wait for that to go in to get a better read on this. |
Still lots of missed contexts, will look into juicing up SPMI collections with extra queries. |
So how does this sound: a public API for static ClassLayout* Create(Compiler* compiler, CORINFO_CLASS_HANDLE classHandle);
static ClassLayout* CreateBox(Compiler* compiler, ClassLayout* payloadLayout);
static ClassLayout* CreateBlock(Compiler* compiler, unsigned length);
static ClassLayout* CreateCustom(Compiler* compiler, unsigned length);
static void AddRepeatingElements(unsigned offset, ClassLayout* elementLayout, unsigned count);
static void AddGCFields(unsigned offset, unsigned count);
void Finalize(); where a custom layout allows adding GC references until The The If this sounds like what you had in mind I will work it up as a separate change and then come back to building this on top. |
I would suggest a new |
No description provided.