-
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
[Mono] Use dn_vector_t instead of GArray in a few places #84027
Conversation
Set up the infrastructure to consume shared container types from src/mono/{metadata,mini}. Replace one use of GArray with dn_vector_t
fyi @lateralusX |
Use a stack allocated container (with heap-allocated data) to avoid one extra allocation
Add a way to specify target_link_libraries for runtime components. Use it to link in the shared containers. Avoids duplicate linking of the container objects in static linking scenarios.
ab17450
to
6029c33
Compare
This is just a start. There are around 20 uses of And after that there's 289 |
Azure Pipelines successfully started running 1 pipeline(s). |
b567e8b
to
3bffcf2
Compare
3bffcf2
to
71fb5c2
Compare
5bb2c06
to
fa05fbf
Compare
fix windows include problems, I guess?
@LakshanF could you take a look at the nativeaot (and coreclr?) bit. There's just one thing here: I'm adding a checked fast fail macro The nativeaot version just ignores the message for now and calls |
@@ -0,0 +1,19 @@ | |||
// Licensed to the .NET Foundation under one or more agreements. |
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.
Shouldn't the naming of this file follow the naming of the header, dn-rt-mono.c?
@@ -78,7 +79,8 @@ mono_debug_open_method (MonoCompile *cfg) | |||
g_assert (header); | |||
|
|||
info->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1); | |||
info->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry)); | |||
info->line_numbers = dn_vector_alloc_t (MonoDebugLineNumberEntry); | |||
dn_checkfail (info->line_numbers != NULL, "Allocation failed"); |
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.
Thinking a little about this pattern, could an alternative be to have a new vector attribute that we can set when doing custom alloc/init that we fail fast internal, like DN_VECTOR_ATTRIBUTE_FAIL_FAST. That code path is already in the slow path so check this attribute and fail fast if requested instead of returning NULL should not add overhead to fast path. It will be an opt in and you need to use the custom init/alloc to get it, but will reduce need to check returns due to allocation failures in code that doesn't do it. Failures could happen to a number of different functions, alloc/init/push_back/resize etc.
We should still keep option to use dn_checkfail as well of course, but adding the attribute would make it possible to align the type to current Mono allocation failure behaviors.
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 also add a couple of pre defined init structs that enable some values, so instead of needing to declare a struct with this flag set, you can just use the predeclared struct in your custom init/alloc call.
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.
Honestly that all sounds like a huge pain.
I would prefer something like
dn_vector_t *vec = DN_AOK (dn_vector_alloc_t (...));
with something like
#define DN_AOK(expr) ({ void *_ck = (expr); dn_checkfail(_ck != NULL, "Allocation failed"); _ck})
except:
- with proper macros so the file:line is from the caller of
DN_AOK()
, not from the macro definiton - with some
typeof
trick so the whole expression has the same type asexpr
- without using the GCC
({ stmt; expr })
non-standard extension
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 think it could be rather straightforward, and it would simplify case to work similar to how g_array works where it asserts on internal allocation failures, so you could make sure a dn_vector_t would behave the same way with regards to internal allocation failures.
The macro way works as well, but they are not exclusive, both variations could exist. Handle it using macros will of course generate more code around each call to a vector function that could fail (that we didn't check for failures when using g_array), but maybe its good to set the pattern checking return values for the new type right away, instead of offering a lazy fallback. The macro solution would probably be able to validate both pointer as well as bool return cases for failures.
@@ -3939,7 +3941,8 @@ recursively_make_pred_seq_points (TransformData *td, InterpBasicBlock *bb) | |||
{ | |||
SeqPoint ** const MONO_SEQ_SEEN_LOOP = (SeqPoint**)GINT_TO_POINTER(-1); | |||
|
|||
GArray *predecessors = g_array_new (FALSE, TRUE, sizeof (gpointer)); | |||
dn_vector_ptr_t predecessors = {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.
No need to init the dn_vector_ptr_t, it will be memset by dn_vector_ptr_init.
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'm not sure if C compilers (or linters) would like that.
and I also don't particularly like it
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's not an uncommon pattern that you have an unutilized, or partly initialized struct that you pass to an init function setting up the values, avoiding setting the same memory multiple times. I agree that its cleaner code to always initialize things meaning you won't end up with potential initialized memory in the end, just wanted to point out that the init function makes sure full struct will be set, so in this case we will overwrite the same memory multiple times.
@@ -33,7 +35,9 @@ recursively_make_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb) | |||
{ | |||
const gpointer MONO_SEQ_SEEN_LOOP = GINT_TO_POINTER(-1); | |||
|
|||
GArray *predecessors = g_array_new (FALSE, TRUE, sizeof (gpointer)); | |||
|
|||
dn_vector_ptr_t predecessors = {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.
No need to init the dn_vector_ptr_t, it will be memset by dn_vector_ptr_init.
@@ -274,24 +275,27 @@ mono_seq_point_init_next (MonoSeqPointInfo* info, SeqPoint sp, SeqPoint* next) | |||
int i; | |||
guint8* ptr; | |||
SeqPointIterator it; | |||
GArray* seq_points = g_array_new (FALSE, TRUE, sizeof (SeqPoint)); | |||
dn_vector_t seq_points = {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.
No need to init the dn_vector_t, it will be memset by dn_vector_init_t.
Just to give a brief update: I'm probably going to pause on this until Preview 4 is out. Also in the follow-up branch where I try to get rid of all uses of |
Still planning on getting this in (P6)? If not, it would at least be nice to get the additional defines in |
@lateralusX I'll get back to this next week. hope I can at least get the basic infrastructure in place |
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
Set up the infrastructure to consume shared container types from src/mono/{utils,metadata,containers,mini}.
There are about 20 total places where we use GArray. Replace a few of them with dn_vector_t as an experiment to see how using shared containers in Mono will look like.