From 9dec6ae2ea81d46884bf49d2df8b26cc1e28eb12 Mon Sep 17 00:00:00 2001 From: Ryan Lucia Date: Mon, 2 Mar 2020 16:46:03 -0500 Subject: [PATCH] Use GArray instead of GList when getting custom attributes from an image (#32974) Xamarin.Forms calls this _constantly_ during startup, to the point where the malloc calls were actually showing up in the profile. This should help with that, and gives us some ms back during startup. There are also a bunch of calls that return empty arrays, which in theory could be created in managed for a perf boost. However, it seems the Xamarin.Android team has mostly gotten rid of those calls and that optimization would complicate the code and require changes to our managed CustomAttribute implemented for both legacy and netcore, so I've opted to not check it in for now. If the empty calls continue to show up down the line, I can dig the code back up from my local branch and PR it separately. --- src/mono/mono/metadata/custom-attrs.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index 7bbb1ed..a5e18b2 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -1606,7 +1606,7 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig guint32 cols [MONO_CUSTOM_ATTR_SIZE]; MonoTableInfo *ca; MonoCustomAttrInfo *ainfo; - GList *tmp, *list = NULL; + GArray *attr_array; const char *data; MonoCustomAttrEntry* attr; @@ -1618,20 +1618,22 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig if (!i) return NULL; i --; + // initial size chosen arbitrarily, but default is 16 which is rather small + attr_array = g_array_sized_new (TRUE, TRUE, sizeof (guint32), 128); while (i < ca->rows) { if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx) break; - list = g_list_prepend (list, GUINT_TO_POINTER (i)); + attr_array = g_array_append_val (attr_array, i); ++i; } - len = g_list_length (list); + len = attr_array->len; if (!len) return NULL; ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len); ainfo->num_attrs = len; ainfo->image = image; - for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) { - mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE); + for (i = 0; i < len; ++i) { + mono_metadata_decode_row (ca, g_array_index (attr_array, guint32, i), cols, MONO_CUSTOM_ATTR_SIZE); mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS; switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) { case MONO_CUSTOM_ATTR_TYPE_METHODDEF: @@ -1644,7 +1646,7 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]); break; } - attr = &ainfo->attrs [i - 1]; + attr = &ainfo->attrs [i]; attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error); if (!attr->ctor) { g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image->name, mtoken, mono_error_get_message (error)); @@ -1652,14 +1654,14 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig mono_error_cleanup (error); error_init (error); } else { - g_list_free (list); + g_array_free (attr_array, TRUE); g_free (ainfo); return NULL; } } if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], error)) { - g_list_free (list); + g_array_free (attr_array, TRUE); g_free (ainfo); return NULL; } @@ -1667,7 +1669,7 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig attr->data_size = mono_metadata_decode_value (data, &data); attr->data = (guchar*)data; } - g_list_free (list); + g_array_free (attr_array, TRUE); return ainfo; } -- 2.7.4