Skip to content

Commit 331a290

Browse files
Peter Oberparleiteroberpar
authored andcommitted
genhtml: consolidate calls to c++filt
When using --demanglecpp, call c++filt only once instead of per function. This approach can reduce the run-time for source files with a lot of overloaded functions significantly. Based on idea by [email protected].
1 parent 49b8771 commit 331a290

File tree

1 file changed

+163
-8
lines changed

1 file changed

+163
-8
lines changed

bin/genhtml

Lines changed: 163 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,15 @@
6565
#
6666

6767
use strict;
68-
use File::Basename;
68+
use File::Basename;
69+
use File::Temp qw(tempfile);
6970
use Getopt::Long;
7071
use Digest::MD5 qw(md5_base64);
7172

7273

7374
# Global constants
7475
our $title = "LCOV - code coverage report";
75-
our $lcov_version = 'LCOV version 1.11 pre (CVS $Revision: 1.70 $)';
76+
our $lcov_version = 'LCOV version 1.11 pre (CVS $Revision: 1.71 $)';
7677
our $lcov_url = "http://ltp.sourceforge.net/coverage/lcov.php";
7778
our $tool_name = basename($0);
7879

@@ -672,6 +673,162 @@ sub print_overall_rate($$$$$$$$$)
672673
if ($br_do);
673674
}
674675

676+
sub get_fn_list($)
677+
{
678+
my ($info) = @_;
679+
my %fns;
680+
my @result;
681+
682+
foreach my $filename (keys(%{$info})) {
683+
my $data = $info->{$filename};
684+
my $funcdata = $data->{"func"};
685+
my $sumfnccount = $data->{"sumfnc"};
686+
687+
if (defined($funcdata)) {
688+
foreach my $func_name (keys(%{$funcdata})) {
689+
$fns{$func_name} = 1;
690+
}
691+
}
692+
693+
if (defined($sumfnccount)) {
694+
foreach my $func_name (keys(%{$sumfnccount})) {
695+
$fns{$func_name} = 1;
696+
}
697+
}
698+
}
699+
700+
@result = keys(%fns);
701+
702+
return \@result;
703+
}
704+
705+
#
706+
# rename_functions(info, conv)
707+
#
708+
# Rename all function names in INFO according to CONV: OLD_NAME -> NEW_NAME.
709+
#
710+
711+
sub rename_functions($$)
712+
{
713+
my ($info, $conv) = @_;
714+
715+
foreach my $filename (keys(%{$info})) {
716+
my $data = $info->{$filename};
717+
my $funcdata;
718+
my $testfncdata;
719+
my $sumfnccount;
720+
my %newfuncdata;
721+
my %newsumfnccount;
722+
723+
# funcdata: function name -> line number
724+
$funcdata = $data->{"func"};
725+
foreach my $fn_name (keys(%{$funcdata})) {
726+
$newfuncdata{$conv->{$fn_name}} = $funcdata->{$fn_name};
727+
}
728+
$data->{"func"} = \%newfuncdata;
729+
730+
# testfncdata: test name -> testfnccount
731+
# testfnccount: function name -> execution count
732+
$testfncdata = $data->{"testfnc"};
733+
foreach my $test_name (keys(%{$testfncdata})) {
734+
my $testfnccount = $testfncdata->{$test_name};
735+
my %newtestfnccount;
736+
737+
foreach my $fn_name (keys(%{$testfnccount})) {
738+
$newtestfnccount{$conv->{$fn_name}} =
739+
$testfnccount->{$fn_name};
740+
}
741+
$testfncdata->{$test_name} = \%newtestfnccount;
742+
}
743+
744+
# sumfnccount: function name -> execution count
745+
$sumfnccount = $data->{"sumfnc"};
746+
foreach my $fn_name (keys(%{$sumfnccount})) {
747+
$newsumfnccount{$conv->{$fn_name}} =
748+
$sumfnccount->{$fn_name};
749+
}
750+
$data->{"sumfnc"} = \%newsumfnccount;
751+
}
752+
}
753+
754+
#
755+
# check_unique_conv(CONV)
756+
#
757+
# Check that there is no A in CONV: A -> B where C -> B.
758+
#
759+
760+
sub check_unique_conv($)
761+
{
762+
my ($conv) = @_;
763+
my %rconv;
764+
765+
foreach my $fn_name (keys(%{$conv})) {
766+
my $c = $conv->{$fn_name};
767+
768+
if (defined($rconv{$c})) {
769+
die("ERROR: non-unique c++filt output for ".
770+
"'$fn_name' and '$rconv{$c}!\n");
771+
}
772+
$rconv{$c} = $fn_name;
773+
}
774+
}
775+
776+
#
777+
# demangle_cpp(INFO)
778+
#
779+
# Demangle all function names found in INFO.
780+
#
781+
sub demangle_cpp($)
782+
{
783+
my ($info) = @_;
784+
my $fn_list = get_fn_list($info);
785+
my @fn_list_demangled;
786+
my $tmpfile;
787+
my $handle;
788+
my %demangled;
789+
my $changed;
790+
791+
# Nothing to do
792+
return if (!@$fn_list);
793+
794+
# Write list to temp file
795+
(undef, $tmpfile) = tempfile();
796+
die("ERROR: could not create temporary file") if (!defined($tmpfile));
797+
open($handle, ">", $tmpfile) or
798+
die("ERROR: could not write to $tmpfile: $!\n");
799+
print($handle join("\n", @$fn_list));
800+
close($handle);
801+
802+
# Run c++ filt on tempfile file and parse output, creating a hash
803+
open($handle, "-|", "c++filt < $tmpfile") or
804+
die("ERROR: could not run c++filt: $!\n");
805+
@fn_list_demangled = <$handle>;
806+
close($handle);
807+
unlink($tmpfile) or
808+
warn("WARNING: could not remove temporary file $tmpfile: $!\n");
809+
810+
if (scalar(@fn_list_demangled) != scalar(@$fn_list)) {
811+
die("ERROR: c++filt output not as expected (".
812+
scalar(@fn_list_demangled)." vs ".
813+
scalar(@$fn_list).") lines\n");
814+
}
815+
816+
# Build old_name -> new_name
817+
$changed = 0;
818+
for (my $i = 0; $i < scalar(@$fn_list); $i++) {
819+
chomp($fn_list_demangled[$i]);
820+
$demangled{$fn_list->[$i]} = $fn_list_demangled[$i];
821+
$changed++ if ($fn_list->[$i] ne $fn_list_demangled[$i]);
822+
}
823+
824+
# Should not be necessary but could silently produce incorrect results
825+
check_unique_conv(\%demangled);
826+
827+
info("Demangling $changed function names\n");
828+
829+
# Change all occurrences of function names in INFO
830+
rename_functions($info, \%demangled);
831+
}
675832

676833
#
677834
# gen_html()
@@ -730,6 +887,9 @@ sub gen_html()
730887
%info_data = %{apply_baseline(\%info_data, \%base_data)};
731888
}
732889

890+
# Demangle C++ function names if requested
891+
demangle_cpp(\%info_data) if ($demangle_cpp);
892+
733893
@dir_list = get_dir_list(keys(%info_data));
734894

735895
if ($no_prefix)
@@ -5194,12 +5354,7 @@ END_OF_HTML
51945354
my $count = $sumfncdata->{$name};
51955355
my $countstyle;
51965356

5197-
# Demangle C++ function names if requested
5198-
if ($demangle_cpp) {
5199-
$name = `c++filt "$name"`;
5200-
chomp($name);
5201-
}
5202-
# Escape any remaining special characters
5357+
# Escape special characters
52035358
$name = escape_html($name);
52045359
if ($startline < 1) {
52055360
$startline = 1;

0 commit comments

Comments
 (0)