MonoProfileCoverageInfo* mono_profiler_coverage_alloc (MonoMethod *method, int entries) { MonoProfileCoverageInfo *res; int instrument = FALSE; ProfilerDesc *prof; for (prof = prof_list; prof; prof = prof->next) { /* note that we call the filter on all the profilers even if just * a single one would be enough to instrument a method */ if (prof->coverage_filter_cb) if (prof->coverage_filter_cb (prof->profiler, method)) instrument = TRUE; } if (!instrument) return NULL; mono_profiler_coverage_lock (); if (!coverage_hash) coverage_hash = g_hash_table_new (NULL, NULL); res = g_malloc0 (sizeof (MonoProfileCoverageInfo) + sizeof (void*) * 2 * entries); res->entries = entries; g_hash_table_insert (coverage_hash, method, res); mono_profiler_coverage_unlock (); return res; }
/** * mono_profiler_coverage_get: * @prof: The profiler handle, installed with mono_profiler_install * @method: the method to gather information from. * @func: A routine that will be called back with the results * * If the MONO_PROFILER_INS_COVERAGE flag was active during JIT compilation * it is posisble to obtain coverage information about a give method. * * The function @func will be invoked repeatedly with instances of the * MonoProfileCoverageEntry structure. */ void mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func) { MonoError error; MonoProfileCoverageInfo* info = NULL; int i, offset; guint32 code_size; const unsigned char *start, *end, *cil_code; MonoMethodHeader *header; MonoProfileCoverageEntry entry; MonoDebugMethodInfo *debug_minfo; mono_profiler_coverage_lock (); if (coverage_hash) info = (MonoProfileCoverageInfo *)g_hash_table_lookup (coverage_hash, method); mono_profiler_coverage_unlock (); if (!info) return; header = mono_method_get_header_checked (method, &error); mono_error_assert_ok (&error); start = mono_method_header_get_code (header, &code_size, NULL); debug_minfo = mono_debug_lookup_method (method); end = start + code_size; for (i = 0; i < info->entries; ++i) { cil_code = info->data [i].cil_code; if (cil_code && cil_code >= start && cil_code < end) { char *fname = NULL; offset = cil_code - start; entry.iloffset = offset; entry.method = method; entry.counter = info->data [i].count; entry.line = entry.col = 1; entry.filename = NULL; if (debug_minfo) { MonoDebugSourceLocation *location; location = mono_debug_symfile_lookup_location (debug_minfo, offset); if (location) { entry.line = location->row; entry.col = location->column; entry.filename = fname = g_strdup (location->source_file); mono_debug_free_source_location (location); } } func (prof, &entry); g_free (fname); } } mono_metadata_free_mh (header); }
/* safe only when the method antive code has been unloaded */ void mono_profiler_coverage_free (MonoMethod *method) { MonoProfileCoverageInfo* info; mono_profiler_coverage_lock (); if (!coverage_hash) { mono_profiler_coverage_unlock (); return; } info = g_hash_table_lookup (coverage_hash, method); if (info) { g_free (info); g_hash_table_remove (coverage_hash, method); } mono_profiler_coverage_unlock (); }