From 8e3df46a026cd65c51ae98d9236004debb596aa3 Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Fri, 29 Jan 2021 10:31:14 -0500 Subject: [PATCH] [mbr] Add a global has_updates flag Use it to take the slow path in metadata lookups when there's at least one delta applied. --- src/mono/mono/metadata/metadata-internals.h | 23 +++++++++-- src/mono/mono/metadata/metadata-update.c | 18 +++++++++ src/mono/mono/metadata/metadata.c | 44 +++++++++++++++++++-- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 94b9483907701f..0e6bf2429ecf84 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -910,20 +910,37 @@ void mono_image_append_class_to_reflection_info_set (MonoClass *klass); #ifndef ENABLE_METADATA_UPDATE +static inline gboolean +mono_metadata_has_updates (void) +{ + return FALSE; +} + static inline void mono_image_effective_table (const MonoTableInfo **t, int *idx) { } #else /* ENABLE_METADATA_UPDATE */ +extern int mono_metadata_update_has_updates_private; + +/* returns TRUE if there's at least one update */ +static inline gboolean +mono_metadata_has_updates (void) +{ + return mono_metadata_update_has_updates_private != 0; +} + void mono_image_effective_table_slow (const MonoTableInfo **t, int *idx); static inline void mono_image_effective_table (const MonoTableInfo **t, int *idx) { - if (G_LIKELY (*idx < (*t)->rows)) - return; - mono_image_effective_table_slow (t, idx); + if (G_UNLIKELY (mono_metadata_has_updates ())) { + if (G_UNLIKELY (*idx >= (*t)->rows)) { + mono_image_effective_table_slow (t, idx); + } + } } int diff --git a/src/mono/mono/metadata/metadata-update.c b/src/mono/mono/metadata/metadata-update.c index ec8eead569301f..f1737a2f10c7d8 100644 --- a/src/mono/mono/metadata/metadata-update.c +++ b/src/mono/mono/metadata/metadata-update.c @@ -32,6 +32,11 @@ static MonoNativeTlsKey exposed_generation_id; #define UPDATE_DEBUG(stmt) /*empty */ #endif +/* + * set to non-zero if at least one update has been published. + */ +int mono_metadata_update_has_updates_private; + /* For each delta image, for each table: * - the total logical number of rows for the previous generation * - the number of modified rows in the current generation @@ -172,6 +177,7 @@ metadata_update_local_generation (MonoImage *base, MonoImage *delta); void mono_metadata_update_init (void) { + mono_metadata_update_has_updates_private = 0; table_to_image_init (); mono_native_tls_alloc (&exposed_generation_id, NULL); } @@ -232,6 +238,15 @@ thread_set_exposed_generation (uint32_t value) mono_native_tls_set_value (exposed_generation_id, GUINT_TO_POINTER((guint)value)); } +/** + * LOCKING: assumes the publish_lock is held + */ +static void +metadata_update_set_has_updates (void) +{ + mono_metadata_update_has_updates_private = 1; +} + uint32_t mono_metadata_update_prepare (MonoDomain *domain) { mono_lazy_initialize (&metadata_update_lazy_init, initialize); @@ -240,6 +255,8 @@ mono_metadata_update_prepare (MonoDomain *domain) { */ publish_lock (); uint32_t alloc_gen = ++update_alloc_frontier; + /* Have to set this here so the updater starts using the slow path of metadata lookups */ + metadata_update_set_has_updates (); /* Expose the alloc frontier to the updater thread */ thread_set_exposed_generation (alloc_gen); return alloc_gen; @@ -320,6 +337,7 @@ mono_image_append_delta (MonoImage *base, MonoImage *delta) return; } g_assert (((MonoImage*)base->delta_image_last->data)->generation < delta->generation); + /* FIXME: g_list_append returns the previous end of the list, not the newly appended element! */ base->delta_image_last = g_list_append (base->delta_image_last, delta); } diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index d3416e5af78bc6..a96d9bb8fa4191 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -1339,6 +1339,9 @@ dword_align (const unsigned char *ptr) return (const unsigned char *) (((gsize) (ptr + 3)) & ~3); } +static void +mono_metadata_decode_row_slow (const MonoTableInfo *t, int idx, guint32 *res, int res_size); + /** * mono_metadata_decode_row: * \param t table to extract information from. @@ -1351,8 +1354,17 @@ dword_align (const unsigned char *ptr) void mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size) { - mono_image_effective_table (&t, &idx); + if (G_UNLIKELY (mono_metadata_has_updates ())) { + mono_metadata_decode_row_slow (t, idx, res, res_size); + } else { + mono_metadata_decode_row_raw (t, idx, res, res_size); + } +} +void +mono_metadata_decode_row_slow (const MonoTableInfo *t, int idx, guint32 *res, int res_size) +{ + mono_image_effective_table (&t, &idx); mono_metadata_decode_row_raw (t, idx, res, res_size); } @@ -1470,6 +1482,11 @@ mono_metadata_decode_row_dynamic_checked (const MonoDynamicImage *image, const M return TRUE; } +static guint32 +mono_metadata_decode_row_col_raw (const MonoTableInfo *t, int idx, guint col); +static guint32 +mono_metadata_decode_row_col_slow (const MonoTableInfo *t, int idx, guint col); + /** * mono_metadata_decode_row_col: * \param t table to extract information from. @@ -1481,13 +1498,34 @@ mono_metadata_decode_row_dynamic_checked (const MonoDynamicImage *image, const M */ guint32 mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col) +{ + if (G_UNLIKELY (mono_metadata_has_updates ())) { + return mono_metadata_decode_row_col_slow (t, idx, col); + } else { + return mono_metadata_decode_row_col_raw (t, idx, col); + } +} + +guint32 +mono_metadata_decode_row_col_slow (const MonoTableInfo *t, int idx, guint col) +{ + mono_image_effective_table (&t, &idx); + return mono_metadata_decode_row_col_raw (t, idx, col); +} + +/** + * mono_metadata_decode_row_col_raw: + * + * Same as \c mono_metadata_decode_row_col but doesn't look for the effective + * table on metadata updates. + */ +guint32 +mono_metadata_decode_row_col_raw (const MonoTableInfo *t, int idx, guint col) { int i; const char *data; int n; - mono_image_effective_table (&t, &idx); - guint32 bitfield = t->size_bitfield; g_assert (idx < t->rows);