File Coverage

blib/lib/Devel/NYTProf/FileInfo.pm
Criterion Covered Total %
statement 254 271 93.7
branch 62 96 64.5
condition 26 40 65.0
subroutine 46 46 100.0
pod 2 35 5.7
total 390 488 79.9


line stmt bran cond sub pod time code
1             package Devel::NYTProf::FileInfo; # fid_fileinfo
2              
3             =head1 NAME
4              
5             Devel::NYTProf::FileInfo
6              
7             =head1 METHODS
8              
9             =cut
10              
11 48     48   323 use strict;
  48         118  
  48         1442  
12              
13 48     48   251 use Carp;
  48         136  
  48         2401  
14 48     48   270 use Config;
  48         100  
  48         1869  
15 48     48   268 use List::Util qw(sum);
  48         113  
  48         3291  
16              
17 48     48   20837 use Devel::NYTProf::Util qw(strip_prefix_from_paths trace_level);
  48         585  
  48         4000  
18              
19 48         8203 use Devel::NYTProf::Constants qw(
20             NYTP_FIDf_HAS_SRC NYTP_FIDf_SAVE_SRC NYTP_FIDf_IS_FAKE NYTP_FIDf_IS_PMC
21             NYTP_FIDf_IS_EVAL
22              
23             NYTP_FIDi_FILENAME NYTP_FIDi_EVAL_FID NYTP_FIDi_EVAL_LINE NYTP_FIDi_FID
24             NYTP_FIDi_FLAGS NYTP_FIDi_FILESIZE NYTP_FIDi_FILEMTIME NYTP_FIDi_PROFILE
25             NYTP_FIDi_EVAL_FI NYTP_FIDi_HAS_EVALS NYTP_FIDi_SUBS_DEFINED NYTP_FIDi_SUBS_CALLED
26             NYTP_FIDi_elements
27              
28             NYTP_SCi_CALL_COUNT NYTP_SCi_INCL_RTIME NYTP_SCi_EXCL_RTIME NYTP_SCi_RECI_RTIME
29             NYTP_SCi_REC_DEPTH NYTP_SCi_CALLING_SUB
30             NYTP_SCi_elements
31 48     48   19393 );
  48         147  
32              
33             # extra constants for private elements
34             use constant {
35 48         190274 NYTP_FIDi_meta => NYTP_FIDi_elements + 1,
36             NYTP_FIDi_cache => NYTP_FIDi_elements + 2,
37 48     48   388 };
  48         243  
38              
39 17931     17931 0 100815 sub filename { shift->[NYTP_FIDi_FILENAME()] }
40 465     465 0 2868 sub eval_fid { shift->[NYTP_FIDi_EVAL_FID()] }
41 3825     3825 0 25643 sub eval_line { shift->[NYTP_FIDi_EVAL_LINE()] }
42 22225     22225 0 119662 sub fid { shift->[NYTP_FIDi_FID()] }
43 1     1 0 5 sub size { shift->[NYTP_FIDi_FILESIZE()] }
44 1     1 0 5 sub mtime { shift->[NYTP_FIDi_FILEMTIME()] }
45 2636     2636 0 8679 sub profile { shift->[NYTP_FIDi_PROFILE()] }
46 387     387 0 1543 sub flags { shift->[NYTP_FIDi_FLAGS()] }
47              
48             # if an eval then return fileinfo obj for the fid that executed the eval
49 18     18 0 104 sub eval_fi { shift->[NYTP_FIDi_EVAL_FI()] }
50             # is_eval is true only for simple string evals (doesn't consider NYTP_FIDf_IS_EVAL)
51 30 50   30 0 275 sub is_eval { shift->[NYTP_FIDi_EVAL_FI()] ? 1 : 0 }
52              
53 23     23 0 65 sub is_fake { shift->flags & NYTP_FIDf_IS_FAKE }
54             sub is_file {
55 4     4 0 18 my $self = shift;
56 4   33     10 return not ($self->is_fake or $self->is_eval or $self->flags & NYTP_FIDf_IS_EVAL());
57             }
58              
59             # general purpose hash - mainly a hack to help kill off Reader.pm
60 646   100 646 0 7954 sub meta { shift->[NYTP_FIDi_meta()] ||= {} }
61             # general purpose cache
62 928   100 928 0 8373 sub cache { shift->[NYTP_FIDi_cache()] ||= {} }
63              
64             # array of fileinfo's for each string eval in the file
65             sub has_evals {
66 4078     4078 0 10036 my ($self, $include_nested) = @_;
67              
68 4078 100       18654 my $eval_fis = $self->[NYTP_FIDi_HAS_EVALS()]
69             or return;
70 848 100       4914 return @$eval_fis if !$include_nested;
71              
72 96         348 my @eval_fis = @$eval_fis;
73             # walk down tree of nested evals, adding them to @fi
74 96         432 for (my $i=0; my $fi = $eval_fis[$i]; ++$i) {
75 112         543 push @eval_fis, $fi->has_evals(0);
76             }
77              
78 96         425 return @eval_fis;
79             }
80              
81              
82             sub sibling_evals {
83 1     1 0 3 my ($self) = @_;
84 1 50       3 my $parent_fi = $self->eval_fi
85             or return; # not an eval
86 0         0 my $eval_line = $self->eval_line;
87 0         0 return grep { $_->eval_line == $eval_line } $parent_fi->has_evals;
  0         0  
88             }
89              
90              
91             sub _nullify {
92 224     224   608 my $self = shift;
93 224         1468 @$self = (); # Zap!
94             }
95              
96              
97              
98             # return subs defined as list of SubInfo objects
99             sub subs_defined {
100 1561     1561 0 4444 my ($self, $incl_nested_evals) = @_;
101              
102 1561 50       3931 return map { $_->subs_defined(0) } $self, $self->has_evals(1)
  0         0  
103             if $incl_nested_evals;
104              
105 1561         2716 return values %{ $self->[NYTP_FIDi_SUBS_DEFINED()] };
  1561         14760  
106             }
107              
108             sub subs_defined_sorted {
109 1139     1139 0 4225 my ($self, $incl_nested_evals) = @_;
110 1139         4834 return sort { $a->subname cmp $b->subname } $self->subs_defined($incl_nested_evals);
  3312         10288  
111             }
112              
113             sub _remove_sub_defined {
114 256     256   646 my ($self, $si) = @_;
115 256         973 my $subname = $si->subname;
116 256 50       1148 delete $self->[NYTP_FIDi_SUBS_DEFINED()]->{$subname}
117             or carp sprintf "_remove_sub_defined: sub %s wasn't defined in %d %s",
118             $subname, $self->fid, $self->filename;
119             }
120              
121             sub _add_new_sub_defined {
122 240     240   1126 my ($self, $subinfo) = @_;
123 240         984 my $subname = $subinfo->subname;
124 240   50     1082 my $subs_defined = $self->[NYTP_FIDi_SUBS_DEFINED()] ||= {};
125 240         675 my $existing_si = $subs_defined->{$subname};
126 240 50       884 croak sprintf "sub %s already defined in fid %d %s",
127             $subname, $self->fid, $self->filename
128             if $existing_si;
129              
130 240         1162 $subs_defined->{$subname} = $subinfo;
131             }
132              
133              
134             =head2 sub_call_lines
135              
136             $hash = $fi->sub_call_lines;
137              
138             Returns a reference to a hash containing information about subroutine calls
139             made at individual lines within the source file.
140             Returns undef if no subroutine calling information is available.
141              
142             The keys of the returned hash are line numbers. The values are references to
143             hashes with fully qualified subroutine names as keys. Each hash value is an
144             reference to an array containing an integer call count (how many times the sub
145             was called from that line of that file) and an inclusive time (how much time
146             was spent inside the sub when it was called from that line of that file).
147              
148             For example, if the following was line 42 of a file C:
149              
150             ++$wiggle if foo(24) == bar(42);
151              
152             that line was executed once, and foo and bar were imported from pkg1, then
153             sub_call_lines() would return something like:
154              
155             {
156             42 => {
157             'pkg1::foo' => [ 1, 0.02093 ],
158             'pkg1::bar' => [ 1, 0.00154 ],
159             },
160             }
161              
162             =cut
163              
164 2504     2504 1 11903 sub sub_call_lines { shift->[NYTP_FIDi_SUBS_CALLED()] }
165              
166              
167             =head2 evals_by_line
168              
169             # { line => { fid_of_eval_at_line => $fi, ... }, ... }
170             $hash = $fi->evals_by_line;
171              
172             Returns a reference to a hash containing information about string evals
173             executed at individual lines within a source file.
174              
175             The keys of the returned hash are line numbers. The values are references to
176             hashes with file id integers as keys and FileInfo objects as values.
177              
178             =cut
179              
180             sub evals_by_line {
181 19     19 1 78 my ($self) = @_;
182              
183             # find all fids that have this fid as an eval_fid
184             # { line => { fid_of_eval_at_line => $fi, ... } }
185              
186 19         35 my %evals_by_line;
187 19         63 for my $fi ($self->has_evals) {
188 0         0 $evals_by_line{ $fi->eval_line }->{ $fi->fid } = $fi;
189             }
190              
191 19         213 return \%evals_by_line;
192             }
193              
194              
195             sub line_time_data {
196 468     468 0 1212 my ($self, $levels) = @_;
197 468   100     3755 $levels ||= [ 'line' ];
198             # XXX this can be optimized once the fidinfo contains directs refs to the data
199 468         1306 my $profile = $self->profile;
200 468         1074 my $fid = $self->fid;
201 468         1414 for my $level (@$levels) {
202 468         2992 my $fid_ary = $profile->get_fid_line_data($level);
203 468 50 33     3848 return $fid_ary->[$fid] if $fid_ary && $fid_ary->[$fid];
204             }
205 0         0 return undef;
206             }
207              
208             sub excl_time { # total exclusive time for fid
209 1     1 0 3 my $self = shift;
210 1   50     5 my $line_data = $self->line_time_data([qw(sub block line)])
211             || return undef;
212 1         2 my $excl_time = 0;
213 1         3 for (@$line_data) {
214 19 100       38 next unless $_;
215 6         13 $excl_time += $_->[0];
216             }
217 1         4 return $excl_time;
218             }
219              
220              
221             sub sum_of_stmts_count {
222 16     16 0 10760 my ($self, $incl_nested_evals) = @_;
223              
224 16 50       130 return sum(map { $_->sum_of_stmts_count(0) } $self, $self->has_evals(1))
  0         0  
225             if $incl_nested_evals;
226              
227 16         94 my $ref = \$self->cache->{NYTP_FIDi_sum_stmts_count};
228 16 50       164 $$ref = $self->_sum_of_line_time_data(1)
229             if not defined $$ref;
230              
231 16         143 return $$ref;
232             }
233              
234             sub sum_of_stmts_time {
235 16     16 0 43 my ($self, $incl_nested_evals) = @_;
236              
237 16 50       52 return sum(map { $_->sum_of_stmts_time(0) } $self, $self->has_evals(1))
  0         0  
238             if $incl_nested_evals;
239              
240 16         72 my $ref = \$self->cache->{NYTP_FIDi_sum_stmts_times};
241 16 50       80 $$ref = $self->_sum_of_line_time_data(0)
242             if not defined $$ref;
243              
244 16         76 return $$ref;
245             }
246              
247             sub _sum_of_line_time_data {
248 32     32   88 my ($self, $idx) = @_;
249 32         83 my $line_time_data = $self->line_time_data;
250 32         72 my $sum = 0;
251 32   100     361 $sum += $_->[$idx]||0 for @$line_time_data;
252 32         103 return $sum;
253             }
254              
255              
256             sub outer {
257 1     1 0 3 my ($self, $recurse) = @_;
258 1 50       4 my $fi = $self->eval_fi
259             or return;
260 0         0 my $prev = $self;
261              
262 0   0     0 while ($recurse and my $eval_fi = $fi->eval_fi) {
263 0         0 $prev = $fi;
264 0         0 $fi = $eval_fi;
265             }
266 0 0       0 return $fi unless wantarray;
267 0         0 return ($fi, $prev->eval_line);
268             }
269              
270              
271             sub is_pmc {
272 359     359 0 1016 return (shift->flags & NYTP_FIDf_IS_PMC());
273             }
274              
275              
276             sub collapse_sibling_evals {
277 192     192 0 980 my ($self, $survivor_fi, @donors) = @_;
278 192         631 my $profile = $self->profile;
279              
280             die "Can't collapse_sibling_evals of non-sibling evals"
281 192 50       496 if grep { $_->eval_fid != $survivor_fi->eval_fid or
  224 50       806  
282             $_->eval_line != $survivor_fi->eval_line
283             } @donors;
284              
285 192         1309 my $s_ltd = $survivor_fi->line_time_data; # XXX line only
286 192         825 my $s_scl = $survivor_fi->sub_call_lines;
287 192         389 my %donor_fids;
288              
289 192         1004 for my $donor_fi (@donors) {
290             # copy data from donor to survivor_fi then delete donor
291 224         787 my $donor_fid = $donor_fi->fid;
292 224         1463 $donor_fids{$donor_fid} = $donor_fi;
293              
294 224 50       1201 warn sprintf "collapse_sibling_evals: processing donor fid %d: %s\n",
295             $donor_fid, $donor_fi->filename
296             if trace_level() >= 3;
297              
298             # XXX nested evals not handled yet
299 224 50       675 warn sprintf "collapse_sibling_evals: nested evals in %s not handled",
300             $donor_fi->filename
301             if $donor_fi->has_evals;
302              
303             # for each sub defined in the donor,
304             # move the sub definition to the survivor
305 224 100       833 if (my @subs_defined = $donor_fi->subs_defined) {
306              
307 128         429 for my $si (@subs_defined) {
308 128 50       605 warn sprintf " - moving from fid %d: sub %s\n",
309             $donor_fid, $si->subname
310             if trace_level() >= 4;
311 128         1431 $si->_alter_fileinfo($donor_fi, $survivor_fi);
312 128 50       642 warn sprintf " - moving done\n"
313             if trace_level() >= 4;
314             }
315             }
316              
317             # for each sub call made by the donor,
318             # move the sub calls to the survivor
319             # 1 => { 'main::foo' => [ 1, '1.38e-05', '1.24e-05', ..., { 'main::RUNTIME' => undef } ] }
320 224 50       707 if (my $sub_call_lines = $donor_fi->sub_call_lines) {
321              
322 224         457 my %subnames_called_by_donor;
323              
324             # merge details of subs called from $donor_fi
325 224         1169 while ( my ($line, $sc_hash) = each %$sub_call_lines ) {
326 176   50     723 my $s_sc_hash = $s_scl->{$line} ||= {};
327 176         921 for my $subname (keys %$sc_hash ) {
328 176   100     945 my $s_sc_info = $s_sc_hash->{$subname} ||= [];
329 176         519 my $sc_info = delete $sc_hash->{$subname};
330 176         2121 Devel::NYTProf::SubInfo::_merge_in_caller_info($s_sc_info, $sc_info,
331             tag => "line $line calls to $subname",
332             );
333              
334 176         1525 $subnames_called_by_donor{$subname}++;
335             }
336             }
337 224         815 %$sub_call_lines = (); # zap
338              
339             # update subinfo (NYTP_SIi_CALLED_BY)
340             $profile->subinfo_of($_)->_alter_called_by_fileinfo($donor_fi, $survivor_fi)
341 224         1974 for keys %subnames_called_by_donor;
342             }
343              
344             # copy line time data
345 224   50     807 my $d_ltd = $donor_fi->line_time_data || []; # XXX line only
346 224         1348 for my $line (0..@$d_ltd-1) {
347 544 100       1639 my $d_tld_l = $d_ltd->[$line] or next;
348 320   50     992 my $s_tld_l = $s_ltd->[$line] ||= [];
349 320         1278 $s_tld_l->[$_] += $d_tld_l->[$_] for (0..@$d_tld_l-1);
350 320         661 warn sprintf "%d:%d: @$s_tld_l from @$d_tld_l fid:%d\n",
351             $survivor_fi->fid, $line, $donor_fid if 0;
352             }
353              
354 224         440 push @{ $survivor_fi->meta->{merged_fids} }, $donor_fid;
  224         885  
355             ++$survivor_fi->meta->{merged_fids_src_varied}
356 224 50       877 if $donor_fi->src_digest ne $survivor_fi->src_digest;
357              
358 224         1505 $donor_fi->_nullify;
359             }
360              
361             # remove donors from parent NYTP_FIDi_HAS_EVALS
362 192 50       1300 if (my $eval_fis = $self->[NYTP_FIDi_HAS_EVALS()]) {
363 192         595 my %donors = map { +"$_" => 1 } @donors;
  224         2322  
364 192         661 my $count = @$eval_fis;
365 192         522 @$eval_fis = grep { !$donors{$_} } @$eval_fis;
  722         2217  
366 192 50       1455 warn "_delete_eval mismatch"
367             if @$eval_fis != $count - @donors;
368             }
369              
370             # update sawampersand_fid if it's one of the now-dead donors
371 192 50 50     1155 if ($donor_fids{ $profile->attributes->{sawampersand_fid} || 0 }) {
372 0         0 $profile->attributes->{sawampersand_fid} = $survivor_fi->fid;
373             }
374              
375             # now the fid merging is complete...
376             # look for any anon subs that are effectively duplicates
377             # (ie have the same name except for eval seqn)
378             # if more than one for any given name we merge them
379 192 100       1020 if (my @subs_defined = $survivor_fi->subs_defined_sorted) {
380              
381             # bucket anon subs by normalized name
382 112         249 my %newname;
383 112         304 for my $si (@subs_defined) {
384 240 50       1326 next unless $si->is_anon;
385 240         864 (my $newname = $si->subname) =~ s/ \( ((?:re_)?) eval \s \d+ \) /(${1}eval 0)/xg;
386 240         624 push @{ $newname{$newname} }, $si;
  240         1542  
387             }
388              
389 112         775 while ( my ($newname, $to_merge) = each %newname ) {
390 112         283 my $survivor_si = shift @$to_merge;
391 112 50       309 next unless @$to_merge; # nothing to do
392              
393 112         362 my $survivor_subname = $survivor_si->subname;
394             warn sprintf "collapse_sibling_evals: merging %d subs into %s: %s\n",
395             scalar @$to_merge, $survivor_subname,
396 112 50       521 join ", ", map { $_->subname } @$to_merge
  0         0  
397             if trace_level() >= 3;
398              
399 112         408 for my $delete_si (@$to_merge) {
400 128         388 my $delete_subname = $delete_si->subname;
401              
402             # for every file that called this sub, find the lines that made the calls
403             # and change the name to the new sub
404 128         664 for my $caller_fid ($delete_si->caller_fids) {
405 128         819 my $caller_fi = $profile->fileinfo_of($caller_fid);
406             # sub_call_lines ==> { line => { sub => ... } }
407 128         259 for my $subs_called_on_line (values %{ $caller_fi->sub_call_lines }) {
  128         319  
408 704 100       1740 my $sc_info = delete $subs_called_on_line->{$delete_subname}
409             or next;
410 128   50     532 my $s_sc_info = $subs_called_on_line->{$survivor_subname} ||= [];
411 128         660 Devel::NYTProf::SubInfo::_merge_in_caller_info($s_sc_info, $sc_info,
412             tag => "collapse eval $delete_subname",
413             );
414             }
415             }
416              
417 128         641 $survivor_si->merge_in($delete_si);
418 128         425 $survivor_fi->_remove_sub_defined($delete_si);
419 128         588 $profile->_disconnect_subinfo($delete_si);
420             }
421             }
422             }
423              
424 192 50       999 warn sprintf "collapse_sibling_evals done for ".$survivor_fi->filename."\n"
425             if trace_level() >= 2;
426              
427 192         785 return $survivor_fi;
428             }
429              
430              
431             # Should return the filename that the application used when loading the file
432             # For evals should remove the @INC portion from within the "(eval N)[$path]"
433             # and similarly for Class::MOP #line evals "... defined at $path".
434             # This is a bit of a fudge. Filename handling should be improved in the profiler.
435             sub filename_without_inc {
436 989     989 0 2748 my $self = shift;
437 989         2861 my $f = [$self->filename];
438 989         3568 strip_prefix_from_paths([$self->profile->inc], $f,
439             qr/(?: ^ | \[ | \sdefined\sat\s )/x
440             );
441 989         6819 return $f->[0];
442             }
443              
444              
445             sub abs_filename {
446 343     343 0 781 my $self = shift;
447              
448 343         1216 my $filename = $self->filename;
449              
450             # strip of autosplit annotation, if any
451 343         1236 $filename =~ s/ \(autosplit into .*//;
452              
453             # if it's a .pmc then assume that's the file we want to look at
454             # (because the main use for .pmc's are related to perl6)
455 343 50       1139 $filename .= "c" if $self->is_pmc;
456              
457             # search profile @INC if filename is not absolute
458 343         1065 my @files = ($filename);
459 343 100       1220 if ($filename !~ m/^\//) {
460 340         825 my @inc = $self->profile->inc;
461 340         966 @files = map { "$_/$filename" } @inc;
  4420         11485  
462             }
463              
464 343         1147 for my $file (@files) {
465 4423 50       45544 return $file if -f $file;
466             }
467              
468             # returning the still-relative filename is better than returning an undef
469 343         1888 return $filename;
470             }
471              
472             # has source code stored within the profile data file
473             sub has_savesrc {
474 630     630 0 1137 my $self = shift;
475 630         1771 return $self->profile->{fid_srclines}[ $self->fid ];
476             }
477              
478             sub srclines_array {
479 627     627 0 11850 my $self = shift;
480              
481 627 100       1759 if (my $srclines = $self->has_savesrc) {
482 300         1013 my $copy = [ @$srclines ]; # shallow clone
483 300         655 shift @$copy; # line 0 not used
484 300         1213 return $copy;
485             }
486              
487 327         1326 my $filename = $self->abs_filename;
488 327 50       7249 if (open my $fh, "<", $filename) {
489 0         0 return [ <$fh> ];
490             }
491              
492 327         3202 return undef;
493             }
494              
495             sub src_digest {
496 896     896 0 1803 my $self = shift;
497 896   100     2449 return $self->cache->{src_digest} ||= do {
498 608   100     2241 my $srclines_array = $self->srclines_array || [];
499 608         2087 my $src = join "\n", @$srclines_array;
500             # return empty string for digest if there's no src
501 608 100       5788 ($src) ? join ",", (
502             scalar @$srclines_array, # number of lines
503             length $src, # total length
504             unpack("%32C*",$src) ) # 32-bit checksum
505             : '';
506             };
507             }
508              
509              
510             sub normalize_for_test {
511 963     963 0 3236 my $self = shift;
512              
513             # normalize eval sequence numbers in 'file' names to 0
514             $self->[NYTP_FIDi_FILENAME] =~ s/ \( ((?:re_)?) eval \s \d+ \) /(${1}eval 0)/xg
515 963 100       9238 if not $ENV{NYTPROF_TEST_SKIP_EVAL_NORM};
516              
517             # normalize flags to avoid failures due to savesrc and perl version
518 963         3099 $self->[NYTP_FIDi_FLAGS] &= ~(NYTP_FIDf_HAS_SRC|NYTP_FIDf_SAVE_SRC);
519              
520             # '1' => { 'main::foo' => [ 1, '1.38e-05', '1.24e-05', ..., { 'main::RUNTIME' => undef } ] }
521 963         1987 for my $subscalled (values %{ $self->sub_call_lines }) {
  963         5839  
522              
523 2283         8068 for my $subname (keys %$subscalled) {
524 2395         5120 my $sc = $subscalled->{$subname};
525 2395         6672 $sc->[NYTP_SCi_INCL_RTIME] =
526             $sc->[NYTP_SCi_EXCL_RTIME] =
527             $sc->[NYTP_SCi_RECI_RTIME] = 0;
528              
529 2395 100       6725 if (not $ENV{NYTPROF_TEST_SKIP_EVAL_NORM}) {
530             # normalize eval sequence numbers in anon sub names to 0
531 2235         6269 (my $newname = $subname) =~ s/ \( ((?:re_)?) eval \s \d+ \) /(${1}eval 0)/xg;
532 2235 100       8920 if ($newname ne $subname) {
533             warn "Normalizing $subname to $newname overwrote other called-by data\n"
534 48 50       232 if $subscalled->{$newname};
535 48         347 $subscalled->{$newname} = delete $subscalled->{$subname};
536             }
537             }
538             }
539              
540             }
541             }
542              
543              
544             sub summary {
545 1     1 0 3 my ($fi) = @_;
546 1         4 return sprintf "fid%d: %s",
547             $fi->fid, $fi->filename_without_inc;
548             }
549              
550             sub dump {
551 962     962 0 4456 my ($self, $separator, $fh, $path, $prefix, $opts) = @_;
552              
553 962         2389 my @values = @{$self}[
  962         4615  
554             NYTP_FIDi_FILENAME, NYTP_FIDi_EVAL_FID, NYTP_FIDi_EVAL_LINE, NYTP_FIDi_FID,
555             NYTP_FIDi_FLAGS, NYTP_FIDi_FILESIZE, NYTP_FIDi_FILEMTIME
556             ];
557 962         6111 $values[0] = $self->filename_without_inc;
558             # also remove possible remaining perl version seen in some cpantesters
559             # http://www.cpantesters.org/cpan/report/bf913910-bfdd-11df-a657-c9f38a00995b
560 962         6327 $values[0] =~ s!^$Config{version}/!!o;
561              
562 962 50       3542 printf $fh "%s[ %s ]\n", $prefix, join(" ", map { defined($_) ? $_ : 'undef' } @values);
  6734         20651  
563              
564 962 100       5484 if (not $opts->{skip_internal_details}) {
565              
566 946         5074 for my $si ($self->subs_defined_sorted) {
567 2252         8151 my ($fl, $ll) = ($si->first_line, $si->last_line);
568 2252   100     9289 defined $_ or $_ = 'undef' for ($fl, $ll);
569 2252         6486 printf $fh "%s%s%s%s%s%s-%s\n",
570             $prefix, 'sub', $separator,
571             $si->subname(' and '), $separator,
572             $fl, $ll;
573             }
574              
575             # { line => { subname => [...] }, ... }
576 946         3319 my $sub_call_lines = $self->sub_call_lines;
577 946         3732 for my $line (sort { $a <=> $b } keys %$sub_call_lines) {
  3380         6778  
578 2146         5012 my $subs_called = $sub_call_lines->{$line};
579              
580 2146         5839 for my $subname (sort keys %$subs_called) {
581 2210         3668 my @sc = @{$subs_called->{$subname}};
  2210         6859  
582 2210         4298 $sc[NYTP_SCi_CALLING_SUB] = join "|", sort keys %{ $sc[NYTP_SCi_CALLING_SUB] };
  2210         7732  
583              
584             printf $fh "%s%s%s%s%s%s%s[ %s ]\n",
585             $prefix, 'call', $separator,
586             $line, $separator, $subname, $separator,
587 2210 50       6643 join(" ", map { defined($_) ? $_ : 'undef' } @sc)
  17680         48970  
588             }
589             }
590              
591             # string evals, group by the line the eval is on
592 946         2407 my %eval_lines;
593 946         3070 for my $eval_fi ($self->has_evals(0)) {
594 416         778 push @{ $eval_lines{ $eval_fi->eval_line } }, $eval_fi;
  416         1050  
595             }
596 946         7361 for my $line (sort { $a <=> $b } keys %eval_lines) {
  102         353  
597 368         862 my $eval_fis = $eval_lines{$line};
598              
599 368         830 my @has_evals = map { $_->has_evals(1) } @$eval_fis;
  416         926  
600 368 100       1009 my @merged_fids = map { @{ $_->meta->{merged_fids}||[]} } @$eval_fis;
  416         664  
  416         1174  
601              
602 368         1598 printf $fh "%s%s%s%d%s[ count %d nested %d merged %d ]\n",
603             $prefix, 'eval', $separator,
604             $eval_fis->[0]->eval_line, $separator,
605             scalar @$eval_fis, # count of evals executed on this line
606             scalar @has_evals, # count of nested evals they executed
607             scalar @merged_fids, # count of evals merged (collapsed) away
608             }
609              
610             }
611              
612             }
613              
614             # vim: ts=8:sw=4:et
615             1;