diff --git a/src/mono/mono/metadata/loader.c b/src/mono/mono/metadata/loader.c index c8bbdbd242638..e9a0cce8ef43e 100644 --- a/src/mono/mono/metadata/loader.c +++ b/src/mono/mono/metadata/loader.c @@ -2001,6 +2001,7 @@ get_method_update_rva (MonoImage *image_base, uint32_t idx) { gpointer loc = NULL; uint32_t cur = mono_metadata_update_get_thread_generation (); + int generation = -1; GList *ptr = image_base->delta_image; /* Go through all the updates that the current thread can see and see * if they updated the method. Keep the latest visible update */ @@ -2008,9 +2009,18 @@ get_method_update_rva (MonoImage *image_base, uint32_t idx) MonoImage *image_delta = (MonoImage*) ptr->data; if (image_delta->generation > cur) break; - if (image_delta->method_table_update) - loc = g_hash_table_lookup (image_delta->method_table_update, GUINT_TO_POINTER (idx)); + if (image_delta->method_table_update) { + gpointer result = g_hash_table_lookup (image_delta->method_table_update, GUINT_TO_POINTER (idx)); + /* if it's not in the table of a later generation, the + * later generation didn't modify the method + */ + if (result != NULL) { + loc = result; + generation = image_delta->generation; + } + } } + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_METADATA_UPDATE, "method lookup idx=0x%08x returned gen=%d il=%p", idx, generation, loc); return loc; } #endif diff --git a/src/mono/mono/metadata/metadata-update.c b/src/mono/mono/metadata/metadata-update.c index e5e91ce2f642f..649dde3673c61 100644 --- a/src/mono/mono/metadata/metadata-update.c +++ b/src/mono/mono/metadata/metadata-update.c @@ -635,11 +635,17 @@ mono_image_relative_delta_index (MonoImage *image_dmeta, int token) g_assert (delta_info); int index_map = delta_info->enc_recs [table]; + int encmap_rows = table_info_get_rows (encmap); + + /* if the table didn't have any updates in this generation and the + * table index is bigger than the last table that got updates, + * enc_recs will point past the last row */ + if (index_map - 1 == encmap_rows) + return -1; guint32 cols[MONO_ENCMAP_SIZE]; mono_metadata_decode_row (encmap, index_map - 1, cols, MONO_ENCMAP_SIZE); int map_entry = cols [MONO_ENCMAP_TOKEN]; - int encmap_rows = table_info_get_rows (encmap); while (mono_metadata_token_table (map_entry) == table && mono_metadata_token_index (map_entry) < index && index_map < encmap_rows) { mono_metadata_decode_row (encmap, ++index_map - 1, cols, MONO_ENCMAP_SIZE); map_entry = cols [MONO_ENCMAP_TOKEN]; @@ -849,6 +855,7 @@ apply_enclog_pass1 (MonoImage *image_base, MonoImage *image_dmeta, gconstpointer static void set_update_method (MonoImage *image_base, uint32_t generation, MonoImage *image_dmeta, uint32_t token_index, const char* il_address) { + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_METADATA_UPDATE, "setting method 0x%08x in g=%d IL=%p", token_index, generation, (void*)il_address); /* FIXME: this is a race if other threads are doing a lookup. */ g_hash_table_insert (image_base->method_table_update, GUINT_TO_POINTER (token_index), GUINT_TO_POINTER (generation)); g_hash_table_insert (image_dmeta->method_table_update, GUINT_TO_POINTER (token_index), (gpointer) il_address);