Skip to content

Commit 04d0eb7

Browse files
richard-finejoncham
authored andcommitted
Store a separate coverage hashtable per MonoDomain and init/cleanup when initing/freeing the domain
1 parent 34a7589 commit 04d0eb7

File tree

5 files changed

+119
-52
lines changed

5 files changed

+119
-52
lines changed

mono/metadata/domain.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,7 @@ mono_domain_create (void)
453453
#endif
454454

455455
mono_debug_domain_create (domain);
456+
mono_profiler_coverage_domain_init (domain);
456457

457458
if (create_domain_hook)
458459
create_domain_hook (domain);
@@ -1270,6 +1271,8 @@ mono_domain_free (MonoDomain *domain, gboolean force)
12701271

12711272
if (domain == mono_root_domain)
12721273
mono_root_domain = NULL;
1274+
1275+
mono_profiler_coverage_domain_free(domain);
12731276
}
12741277

12751278
/**

mono/metadata/profiler-private.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ typedef struct {
5151

5252
gboolean code_coverage;
5353
mono_mutex_t coverage_mutex;
54-
GHashTable *coverage_hash;
54+
MonoDomainCoverage *coverage_domains;
5555

5656
MonoProfilerHandle sampling_owner;
5757
MonoSemType sampling_semaphore;
@@ -112,8 +112,18 @@ mono_profiler_installed (void)
112112
return !!mono_profiler_state.profilers;
113113
}
114114

115-
MonoProfilerCoverageInfo *mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries);
116-
void mono_profiler_coverage_free (MonoMethod* method, MonoProfilerCoverageInfo* info);
115+
MonoProfilerCoverageInfo *mono_profiler_coverage_alloc (MonoDomain* domain, MonoMethod *method, guint32 entries);
116+
117+
struct _MonoDomainCoverage
118+
{
119+
MonoDomain* domain;
120+
GHashTable *coverage_hash;
121+
mono_mutex_t mutex;
122+
MonoDomainCoverage *next;
123+
};
124+
125+
void mono_profiler_coverage_domain_init (MonoDomain* domain);
126+
void mono_profiler_coverage_domain_free (MonoDomain* domain);
117127

118128
struct _MonoProfilerCallContext {
119129
/*

mono/metadata/profiler.c

Lines changed: 100 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ mono_profiler_enable_coverage (void)
248248
return FALSE;
249249

250250
mono_os_mutex_init (&mono_profiler_state.coverage_mutex);
251-
mono_profiler_state.coverage_hash = g_hash_table_new (NULL, NULL);
252251

253252
if (!mono_debug_enabled ())
254253
mono_debug_init (MONO_DEBUG_FORMAT_MONO);
@@ -279,17 +278,89 @@ mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfi
279278
}
280279

281280
static void
282-
coverage_lock (void)
281+
coverage_domains_lock (void)
283282
{
284283
mono_os_mutex_lock (&mono_profiler_state.coverage_mutex);
285284
}
286285

287286
static void
288-
coverage_unlock (void)
287+
coverage_domains_unlock (void)
289288
{
290289
mono_os_mutex_unlock (&mono_profiler_state.coverage_mutex);
291290
}
292291

292+
static MonoDomainCoverage *
293+
get_coverage_for_domain(MonoDomain* domain)
294+
{
295+
coverage_domains_lock();
296+
MonoDomainCoverage* cov = mono_profiler_state.coverage_domains;
297+
while (cov)
298+
{
299+
if (cov->domain == domain)
300+
break;
301+
cov = cov->next;
302+
}
303+
coverage_domains_unlock();
304+
return cov;
305+
}
306+
307+
void
308+
mono_profiler_coverage_domain_init(MonoDomain* domain)
309+
{
310+
if (!mono_profiler_state.code_coverage)
311+
return;
312+
313+
MonoDomainCoverage* cov = g_new0(MonoDomainCoverage, 1);
314+
cov->domain = domain;
315+
cov->coverage_hash = g_hash_table_new(NULL, NULL);
316+
mono_os_mutex_init(&cov->mutex);
317+
318+
coverage_domains_lock();
319+
cov->next = mono_profiler_state.coverage_domains;
320+
mono_profiler_state.coverage_domains = cov;
321+
coverage_domains_unlock();
322+
}
323+
324+
void
325+
mono_profiler_coverage_domain_free(MonoDomain* domain)
326+
{
327+
if (!mono_profiler_state.code_coverage)
328+
return;
329+
330+
coverage_domains_lock();
331+
332+
MonoDomainCoverage* cov = mono_profiler_state.coverage_domains;
333+
MonoDomainCoverage** prev = &mono_profiler_state.coverage_domains;
334+
while (cov)
335+
{
336+
if (cov->domain == domain)
337+
break;
338+
339+
prev = &cov->next;
340+
cov = cov->next;
341+
}
342+
343+
if (cov != NULL)
344+
{
345+
*prev = cov->next;
346+
347+
GHashTableIter iter;
348+
g_hash_table_iter_init (&iter, cov->coverage_hash);
349+
350+
MonoProfilerCoverageInfo *info;
351+
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
352+
g_free (info);
353+
354+
g_hash_table_destroy(cov->coverage_hash);
355+
356+
mono_os_mutex_destroy(&cov->mutex);
357+
358+
g_free(cov);
359+
}
360+
361+
coverage_domains_unlock();
362+
}
363+
293364
/**
294365
* mono_profiler_get_coverage_data:
295366
*
@@ -313,11 +384,13 @@ mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method,
313384
if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
314385
return FALSE;
315386

316-
coverage_lock ();
387+
MonoDomainCoverage* domain = get_coverage_for_domain(mono_domain_get());
317388

318-
MonoProfilerCoverageInfo *info = g_hash_table_lookup (mono_profiler_state.coverage_hash, method);
389+
mono_os_mutex_lock(&domain->mutex);
319390

320-
coverage_unlock ();
391+
MonoProfilerCoverageInfo *info = g_hash_table_lookup (domain->coverage_hash, method);
392+
393+
mono_os_mutex_unlock(&domain->mutex);
321394

322395
MonoError error;
323396
MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
@@ -475,11 +548,13 @@ mono_profiler_get_all_coverage_data(MonoProfilerHandle handle, MonoProfilerCover
475548
info.cb = cb;
476549
info.handle = handle;
477550

478-
coverage_lock ();
551+
MonoDomainCoverage* domain = get_coverage_for_domain(mono_domain_get());
552+
553+
mono_os_mutex_lock(&domain->mutex);
479554

480-
g_hash_table_foreach (mono_profiler_state.coverage_hash, invoke_coverage_callback_for_hashtable_entry, &info);
555+
g_hash_table_foreach (domain->coverage_hash, invoke_coverage_callback_for_hashtable_entry, &info);
481556

482-
coverage_unlock ();
557+
mono_os_mutex_unlock(&domain->mutex);
483558

484559
return TRUE;
485560
}
@@ -493,11 +568,13 @@ mono_profiler_reset_coverage(MonoMethod* method)
493568
if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
494569
return FALSE;
495570

496-
coverage_lock ();
571+
MonoDomainCoverage* domain = get_coverage_for_domain(mono_domain_get());
497572

498-
MonoProfilerCoverageInfo *info = g_hash_table_lookup (mono_profiler_state.coverage_hash, method);
573+
mono_os_mutex_lock(&domain->mutex);
499574

500-
coverage_unlock ();
575+
MonoProfilerCoverageInfo *info = g_hash_table_lookup (domain->coverage_hash, method);
576+
577+
mono_os_mutex_unlock(&domain->mutex);
501578

502579
if (!info)
503580
return TRUE;
@@ -521,17 +598,19 @@ void mono_profiler_reset_all_coverage()
521598
if (!mono_profiler_state.code_coverage)
522599
return;
523600

524-
coverage_lock ();
601+
MonoDomainCoverage* domain = get_coverage_for_domain(mono_domain_get());
602+
603+
mono_os_mutex_lock(&domain->mutex);
525604

526-
g_hash_table_foreach (mono_profiler_state.coverage_hash, reset_coverage_for_hashtable_entry, NULL);
605+
g_hash_table_foreach (domain->coverage_hash, reset_coverage_for_hashtable_entry, NULL);
527606

528-
coverage_unlock ();
607+
mono_os_mutex_unlock(&domain->mutex);
529608
}
530609

531610
#endif
532611

533612
MonoProfilerCoverageInfo *
534-
mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries)
613+
mono_profiler_coverage_alloc (MonoDomain *domain, MonoMethod *method, guint32 entries)
535614
{
536615
if (!mono_profiler_state.code_coverage)
537616
return FALSE;
@@ -551,33 +630,21 @@ mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries)
551630
if (!cover)
552631
return NULL;
553632

554-
coverage_lock ();
633+
MonoDomainCoverage* covdomain = get_coverage_for_domain(domain);
634+
635+
mono_os_mutex_lock(&covdomain->mutex);
555636

556637
MonoProfilerCoverageInfo *info = g_malloc0 (sizeof (MonoProfilerCoverageInfo) + SIZEOF_VOID_P * 2 * entries);
557638

558639
info->entries = entries;
559640

560-
g_hash_table_insert (mono_profiler_state.coverage_hash, method, info);
641+
g_hash_table_insert (covdomain->coverage_hash, method, info);
561642

562-
coverage_unlock ();
643+
mono_os_mutex_unlock(&covdomain->mutex);
563644

564645
return info;
565646
}
566647

567-
void mono_profiler_coverage_free (MonoMethod* method, MonoProfilerCoverageInfo* info)
568-
{
569-
if (!mono_profiler_state.code_coverage)
570-
return;
571-
572-
coverage_lock ();
573-
574-
g_hash_table_remove(mono_profiler_state.coverage_hash, method);
575-
576-
coverage_unlock ();
577-
578-
g_free (info);
579-
}
580-
581648
/**
582649
* mono_profiler_enable_sampling:
583650
*
@@ -972,21 +1039,6 @@ mono_profiler_cleanup (void)
9721039
g_free (cur);
9731040
}
9741041

975-
if (mono_profiler_state.code_coverage) {
976-
mono_os_mutex_destroy (&mono_profiler_state.coverage_mutex);
977-
978-
GHashTableIter iter;
979-
980-
g_hash_table_iter_init (&iter, mono_profiler_state.coverage_hash);
981-
982-
MonoProfilerCoverageInfo *info;
983-
984-
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info))
985-
g_free (info);
986-
987-
g_hash_table_destroy (mono_profiler_state.coverage_hash);
988-
}
989-
9901042
if (mono_profiler_state.sampling_owner)
9911043
mono_os_sem_destroy (&mono_profiler_state.sampling_semaphore);
9921044
}

mono/metadata/profiler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ typedef struct {
3838
uint32_t column;
3939
} MonoProfilerCoverageData;
4040

41+
typedef struct _MonoDomainCoverage MonoDomainCoverage;
42+
4143
typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, MonoMethod *method);
4244
typedef void (*MonoProfilerCoverageCallback) (MonoProfiler *prof, const MonoProfilerCoverageData *data);
4345

mono/mini/method-to-ir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7255,7 +7255,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
72557255
}
72567256

72577257
if (cfg->method == method)
7258-
cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
7258+
cfg->coverage_info = mono_profiler_coverage_alloc (cfg->domain, cfg->method, header->code_size);
72597259
if (cfg->compile_aot && cfg->coverage_info)
72607260
g_error ("Coverage profiling is not supported with AOT.");
72617261

0 commit comments

Comments
 (0)