#include <mono/metadata/mono-config-dirs.h>
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/profiler-private.h>
+#include <mono/metadata/debug-internals.h>
#include <mono/utils/mono-dl.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/mono-logger-internals.h>
coverage_unlock ();
- if (!info)
- return FALSE;
-
MonoError error;
MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
mono_error_assert_ok (&error);
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;
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) {
MonoConcurrentHashTable *image_to_methods;
+ GHashTable *uncovered_methods;
+
guint32 previous_offset;
};
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;
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, "</coverage>\n");
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;