Skip to content
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

Closed

Conversation

lambdageek
Copy link
Member

@lambdageek lambdageek commented Mar 28, 2023

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.

Set up the infrastructure to consume shared container types from
src/mono/{metadata,mini}.

Replace one use of GArray with dn_vector_t
@lambdageek
Copy link
Member Author

fyi @lateralusX

src/mono/mono/metadata/CMakeLists.txt Outdated Show resolved Hide resolved
src/mono/mono/metadata/custom-attrs.c Outdated Show resolved Hide resolved
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.
@lambdageek lambdageek changed the title [Mono] Use dn_vector_t instead of GArray in one place [Mono] Use dn_vector_t instead of GArray in a few places Mar 28, 2023
@lambdageek lambdageek force-pushed the use-shared-containers-in-mono branch from ab17450 to 6029c33 Compare March 28, 2023 20:38
@lambdageek
Copy link
Member Author

This is just a start. There are around 20 uses of g_array_new... in Mono, 89 g_ptr_array_new..., 7 g_byte_array_new.

And after that there's 289 g_hash_table_new... 😱

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@lambdageek lambdageek force-pushed the use-shared-containers-in-mono branch from b567e8b to 3bffcf2 Compare April 6, 2023 00:39
@lambdageek lambdageek force-pushed the use-shared-containers-in-mono branch from 3bffcf2 to 71fb5c2 Compare April 6, 2023 02:16
@lambdageek lambdageek force-pushed the use-shared-containers-in-mono branch from 5bb2c06 to fa05fbf Compare April 6, 2023 02:30
@lambdageek
Copy link
Member Author

lambdageek commented Apr 6, 2023

@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 dn_checkfail(cond,msg,...) that checks if cond is true and if not, fast fails (in both release and debug builds). It's not actually used inside the containers library anywhere, but I want to start using it in Mono as we migrate to the shared containers to preserve our old behavior (unlike asserts in coreclr, mono's g_assert macro fires in both debug and release builds).

The nativeaot version just ignores the message for now and calls RhFastFail. I could try to make it print out the message, but I wasn't sure if there's some Redhawk way of doing that or what the general policy in native aot is around diagnostic output of this sort.

@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
Copy link
Member

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");
Copy link
Member

@lateralusX lateralusX Apr 19, 2023

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.

Copy link
Member

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.

Copy link
Member Author

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:

  1. with proper macros so the file:line is from the caller of DN_AOK(), not from the macro definiton
  2. with some typeof trick so the whole expression has the same type as expr
  3. without using the GCC ({ stmt; expr }) non-standard extension

Copy link
Member

@lateralusX lateralusX Apr 20, 2023

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,};
Copy link
Member

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.

Copy link
Member Author

@lambdageek lambdageek Apr 20, 2023

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

Copy link
Member

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,};
Copy link
Member

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,};
Copy link
Member

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.

@lambdageek
Copy link
Member Author

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 GPtrArray I found a few more cmake tweaks that I need to make. I will bring those over to this PR, too, so we have all the build stuff sorted out.

@lateralusX
Copy link
Member

Still planning on getting this in (P6)? If not, it would at least be nice to get the additional defines in src/native/containers/dn-vector-ptr.h included from this PR.

@lambdageek
Copy link
Member Author

@lateralusX I'll get back to this next week. hope I can at least get the basic infrastructure in place

@lambdageek lambdageek marked this pull request as draft May 23, 2023 15:04
@ghost ghost closed this Jun 22, 2023
@ghost
Copy link

ghost commented Jun 22, 2023

Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it.

@ghost ghost locked as resolved and limited conversation to collaborators Jul 22, 2023
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants