From baac94e4b7429eb60ec264ef9b974dc148618b64 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 5 Oct 2017 17:15:36 +0200 Subject: [PATCH] [runtime] Coverage profiler fixes (#5698) * [runtime] Avoid collecting coverage data for wrappers. * [runtime] Return sensible information for methods which have no coverage info in mono_profiler_get_coverage_data (). * [profiler] Emit coverage info for uncovered methods as well. --- mono/metadata/profiler.c | 46 +++++++++++++++++++++++++++++++++++++--- mono/profiler/coverage.c | 29 ++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/mono/metadata/profiler.c b/mono/metadata/profiler.c index b10423120d4..9f65059f806 100644 --- a/mono/metadata/profiler.c +++ b/mono/metadata/profiler.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -208,9 +209,6 @@ mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, coverage_unlock (); - if (!info) - return FALSE; - MonoError error; MonoMethodHeader *header = mono_method_get_header_checked (method, &error); mono_error_assert_ok (&error); @@ -221,6 +219,45 @@ mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, const unsigned char *end = start + size; MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method); + if (!info) { + char *source_file; + int i, n_il_offsets; + int *source_files; + GPtrArray *source_file_list; + MonoSymSeqPoint *sym_seq_points; + + /* Return 0 counts for all locations */ + + mono_debug_get_seq_points (minfo, &source_file, &source_file_list, &source_files, &sym_seq_points, &n_il_offsets); + for (i = 0; i < n_il_offsets; ++i) { + MonoSymSeqPoint *sp = &sym_seq_points [i]; + const char *srcfile = ""; + + if (source_files [i] != -1) { + MonoDebugSourceInfo *sinfo = (MonoDebugSourceInfo *)g_ptr_array_index (source_file_list, source_files [i]); + srcfile = sinfo->source_file; + } + + MonoProfilerCoverageData data = { + .method = method, + .il_offset = sp->il_offset, + .counter = 0, + .file_name = srcfile, + .line = sp->line, + .column = 0, + }; + + cb (handle->prof, &data); + } + + g_free (source_files); + g_free (sym_seq_points); + g_ptr_array_free (source_file_list, TRUE); + + mono_metadata_free_mh (header); + return TRUE; + } + for (guint32 i = 0; i < info->entries; i++) { guchar *cil_code = info->data [i].cil_code; @@ -264,6 +301,9 @@ mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries) if (!mono_profiler_state.code_coverage) return FALSE; + if (method->wrapper_type) + return FALSE; + gboolean cover = FALSE; for (MonoProfilerHandle handle = mono_profiler_state.profilers; handle; handle = handle->next) { diff --git a/mono/profiler/coverage.c b/mono/profiler/coverage.c index de8f5207b0a..f88e49df626 100644 --- a/mono/profiler/coverage.c +++ b/mono/profiler/coverage.c @@ -112,6 +112,8 @@ struct _MonoProfiler { MonoConcurrentHashTable *image_to_methods; + GHashTable *uncovered_methods; + guint32 previous_offset; }; @@ -357,7 +359,30 @@ dump_classes_for_image (gpointer key, gpointer value, gpointer userdata) class_name = mono_type_get_name (mono_class_get_type (klass)); number_of_methods = mono_class_num_methods (klass); - fully_covered = count_queue (class_methods); + + GHashTable *covered_methods = g_hash_table_new (NULL, NULL); + int count = 0; + { + MonoLockFreeQueueNode *node; + guint count = 0; + + while ((node = mono_lock_free_queue_dequeue (class_methods))) { + MethodNode *mnode = (MethodNode*)node; + g_hash_table_insert (covered_methods, mnode->method, mnode->method); + count++; + mono_thread_hazardous_try_free (node, g_free); + } + } + fully_covered = count; + + gpointer iter = NULL; + MonoMethod *method; + while ((method = mono_class_get_methods (klass, &iter))) { + if (!g_hash_table_lookup (covered_methods, method)) + g_hash_table_insert (coverage_profiler.uncovered_methods, method, method); + } + g_hash_table_destroy (covered_methods); + /* We don't handle partial covered yet */ partially_covered = 0; @@ -428,6 +453,7 @@ dump_coverage (void) mono_os_mutex_lock (&coverage_profiler.mutex); mono_conc_hashtable_foreach (coverage_profiler.assemblies, dump_assembly, NULL); mono_conc_hashtable_foreach (coverage_profiler.methods, dump_method, NULL); + g_hash_table_foreach (coverage_profiler.uncovered_methods, dump_method, NULL); mono_os_mutex_unlock (&coverage_profiler.mutex); fprintf (coverage_profiler.file, "\n"); @@ -901,6 +927,7 @@ mono_profiler_init_coverage (const char *desc) coverage_profiler.classes = mono_conc_hashtable_new (NULL, NULL); coverage_profiler.filtered_classes = mono_conc_hashtable_new (NULL, NULL); coverage_profiler.image_to_methods = mono_conc_hashtable_new (NULL, NULL); + coverage_profiler.uncovered_methods = g_hash_table_new (NULL, NULL); init_suppressed_assemblies (); coverage_profiler.filters = filters; -- 2.25.1