@@ -407,6 +407,115 @@ mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method,
407
407
408
408
return TRUE;
409
409
}
410
+
411
+ static void invoke_coverage_callback_for_hashtable_entry (gpointer key , gpointer value , gpointer user_data )
412
+ {
413
+ MonoMethod * method = (MonoMethod * )key ;
414
+ MonoProfilerCoverageInfo * info = (MonoProfilerCoverageInfo * )value ;
415
+ MonoProfilerCoverageCallback cb = (MonoProfilerCoverageCallback )user_data ;
416
+
417
+ MonoError error ;
418
+ MonoMethodHeader * header = mono_method_get_header_checked (method , & error );
419
+ mono_error_assert_ok (& error );
420
+
421
+ guint32 size ;
422
+
423
+ const unsigned char * start = mono_method_header_get_code (header , & size , NULL );
424
+ const unsigned char * end = start + size ;
425
+ MonoDebugMethodInfo * minfo = mono_debug_lookup_method (method );
426
+
427
+ for (guint32 i = 0 ; i < info -> entries ; i ++ ) {
428
+ guchar * cil_code = info -> data [i ].cil_code ;
429
+
430
+ if (cil_code && cil_code >= start && cil_code < end ) {
431
+ guint32 offset = cil_code - start ;
432
+
433
+ MonoProfilerCoverageData data = {
434
+ .method = method ,
435
+ .il_offset = offset ,
436
+ .counter = info -> data [i ].count ,
437
+ .line = 1 ,
438
+ .column = 1 ,
439
+ };
440
+
441
+ if (minfo ) {
442
+ MonoDebugSourceLocation * loc = mono_debug_method_lookup_location (minfo , offset );
443
+
444
+ if (loc ) {
445
+ data .file_name = g_strdup (loc -> source_file );
446
+ data .line = loc -> row ;
447
+ data .column = loc -> column ;
448
+
449
+ mono_debug_free_source_location (loc );
450
+ }
451
+ }
452
+
453
+ cb (handle -> prof , & data );
454
+
455
+ g_free ((char * ) data .file_name );
456
+ }
457
+ }
458
+
459
+ mono_metadata_free_mh (header );
460
+ }
461
+
462
+ mono_bool
463
+ mono_profiler_get_all_coverage_data (MonoProfilerHandle handle , MonoProfilerCoverageCallback cb )
464
+ {
465
+ if (!mono_profiler_state .code_coverage )
466
+ return FALSE;
467
+
468
+ coverage_lock ();
469
+
470
+ g_hash_table_foreach (mono_profiler_state .coverage_hash , invoke_coverage_callback_for_hashtable_entry , cb );
471
+
472
+ coverage_unlock ();
473
+
474
+ return TRUE;
475
+ }
476
+
477
+ void
478
+ mono_profiler_reset_coverage (MonoMethod * method )
479
+ {
480
+ if (!mono_profiler_state .code_coverage )
481
+ return ;
482
+
483
+ 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 ))
484
+ return ;
485
+
486
+ coverage_lock ();
487
+
488
+ MonoProfilerCoverageInfo * info = g_hash_table_lookup (mono_profiler_state .coverage_hash , method );
489
+
490
+ coverage_unlock ();
491
+
492
+ if (!info )
493
+ return ;
494
+
495
+ for (guint32 i = 0 ; i < info -> entries ; i ++ )
496
+ info -> data [i ].count = 0 ;
497
+ }
498
+
499
+ static void reset_coverage_for_hashtable_entry (gpointer key , gpointer value , gpointer user_data )
500
+ {
501
+ MonoProfilerCoverageInfo * info = (MonoProfilerCoverageInfo * )value ;
502
+
503
+ for (guint32 i = 0 ; i < info -> entries ; i ++ )
504
+ info -> data [i ].count = 0 ;
505
+ }
506
+
507
+ void mono_profiler_reset_all_coverage ()
508
+ {
509
+ if (!mono_profiler_state .code_coverage )
510
+ return ;
511
+
512
+ coverage_lock ();
513
+
514
+ g_hash_table_foreach (mono_profiler_state .coverage_hash , reset_coverage_for_hashtable_entry , NULL );
515
+
516
+ coverage_unlock ();
517
+ }
518
+
410
519
#endif
411
520
412
521
MonoProfilerCoverageInfo *
0 commit comments