| Filename | /usr/local/share/perl/5.18.2/Devel/StackTrace.pm |
| Statements | Executed 19 statements in 1.17ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 642µs | 716µs | Devel::StackTrace::BEGIN@10 |
| 1 | 1 | 1 | 18µs | 18µs | Devel::StackTrace::BEGIN@5 |
| 1 | 1 | 1 | 9µs | 40µs | Devel::StackTrace::BEGIN@15 |
| 1 | 1 | 1 | 7µs | 18µs | Devel::StackTrace::BEGIN@7 |
| 1 | 1 | 1 | 7µs | 7µs | Devel::StackTrace::BEGIN@11 |
| 1 | 1 | 1 | 6µs | 36µs | Devel::StackTrace::BEGIN@12 |
| 1 | 1 | 1 | 6µs | 9µs | Devel::StackTrace::BEGIN@8 |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::__ANON__[:107] |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::__ANON__[:144] |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::_add_frame |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::_make_frame_filter |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::_make_frames |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::_record_caller_data |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::_ref_to_string |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::as_string |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::frame |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::frame_count |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::frames |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::new |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::next_frame |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::prev_frame |
| 0 | 0 | 0 | 0s | 0s | Devel::StackTrace::reset_pointer |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Devel::StackTrace; | ||||
| 2 | # git description: v1.34-10-g810fd3f | ||||
| 3 | |||||
| 4 | 1 | 500ns | $Devel::StackTrace::VERSION = '2.00'; | ||
| 5 | 2 | 40µs | 1 | 18µs | # spent 18µs within Devel::StackTrace::BEGIN@5 which was called:
# once (18µs+0s) by Plack::Middleware::StackTrace::BEGIN@5 at line 5 # spent 18µs making 1 call to Devel::StackTrace::BEGIN@5 |
| 6 | |||||
| 7 | 2 | 17µs | 2 | 28µs | # spent 18µs (7+10) within Devel::StackTrace::BEGIN@7 which was called:
# once (7µs+10µs) by Plack::Middleware::StackTrace::BEGIN@5 at line 7 # spent 18µs making 1 call to Devel::StackTrace::BEGIN@7
# spent 10µs making 1 call to strict::import |
| 8 | 2 | 22µs | 2 | 13µs | # spent 9µs (6+4) within Devel::StackTrace::BEGIN@8 which was called:
# once (6µs+4µs) by Plack::Middleware::StackTrace::BEGIN@5 at line 8 # spent 9µs making 1 call to Devel::StackTrace::BEGIN@8
# spent 4µs making 1 call to warnings::import |
| 9 | |||||
| 10 | 2 | 111µs | 1 | 716µs | # spent 716µs (642+74) within Devel::StackTrace::BEGIN@10 which was called:
# once (642µs+74µs) by Plack::Middleware::StackTrace::BEGIN@5 at line 10 # spent 716µs making 1 call to Devel::StackTrace::BEGIN@10 |
| 11 | 2 | 23µs | 1 | 7µs | # spent 7µs within Devel::StackTrace::BEGIN@11 which was called:
# once (7µs+0s) by Plack::Middleware::StackTrace::BEGIN@5 at line 11 # spent 7µs making 1 call to Devel::StackTrace::BEGIN@11 |
| 12 | 2 | 31µs | 2 | 66µs | # spent 36µs (6+30) within Devel::StackTrace::BEGIN@12 which was called:
# once (6µs+30µs) by Plack::Middleware::StackTrace::BEGIN@5 at line 12 # spent 36µs making 1 call to Devel::StackTrace::BEGIN@12
# spent 30µs making 1 call to Exporter::import |
| 13 | |||||
| 14 | use overload | ||||
| 15 | 1 | 7µs | 1 | 30µs | # spent 40µs (9+31) within Devel::StackTrace::BEGIN@15 which was called:
# once (9µs+31µs) by Plack::Middleware::StackTrace::BEGIN@5 at line 16 # spent 30µs making 1 call to overload::import |
| 16 | 1 | 904µs | 1 | 40µs | fallback => 1; # spent 40µs making 1 call to Devel::StackTrace::BEGIN@15 |
| 17 | |||||
| 18 | sub new { | ||||
| 19 | my $class = shift; | ||||
| 20 | my %p = @_; | ||||
| 21 | |||||
| 22 | $p{unsafe_ref_capture} = !delete $p{no_refs} | ||||
| 23 | if exists $p{no_refs}; | ||||
| 24 | |||||
| 25 | my $self = bless { | ||||
| 26 | index => undef, | ||||
| 27 | frames => [], | ||||
| 28 | raw => [], | ||||
| 29 | %p, | ||||
| 30 | }, $class; | ||||
| 31 | |||||
| 32 | $self->_record_caller_data(); | ||||
| 33 | |||||
| 34 | return $self; | ||||
| 35 | } | ||||
| 36 | |||||
| 37 | sub _record_caller_data { | ||||
| 38 | my $self = shift; | ||||
| 39 | |||||
| 40 | my $filter = $self->{filter_frames_early} && $self->_make_frame_filter(); | ||||
| 41 | |||||
| 42 | # We exclude this method by starting at least one frame back. | ||||
| 43 | my $x = 1 + ( $self->{skip_frames} || 0 ); | ||||
| 44 | |||||
| 45 | while ( | ||||
| 46 | my @c | ||||
| 47 | = $self->{no_args} | ||||
| 48 | ? caller( $x++ ) | ||||
| 49 | : do { | ||||
| 50 | package # the newline keeps dzil from adding a version here | ||||
| 51 | DB; | ||||
| 52 | |||||
| - - | |||||
| 55 | ) { | ||||
| 56 | |||||
| 57 | my @args; | ||||
| 58 | |||||
| 59 | @args = $self->{no_args} ? () : @DB::args; | ||||
| 60 | |||||
| 61 | my $raw = { | ||||
| 62 | caller => \@c, | ||||
| 63 | args => \@args, | ||||
| 64 | }; | ||||
| 65 | |||||
| 66 | next if $filter && !$filter->($raw); | ||||
| 67 | |||||
| 68 | unless ( $self->{unsafe_ref_capture} ) { | ||||
| 69 | $raw->{args} = [ map { ref $_ ? $self->_ref_to_string($_) : $_ } | ||||
| 70 | @{ $raw->{args} } ]; | ||||
| 71 | } | ||||
| 72 | |||||
| 73 | push @{ $self->{raw} }, $raw; | ||||
| 74 | } | ||||
| 75 | } | ||||
| 76 | |||||
| 77 | sub _ref_to_string { | ||||
| 78 | my $self = shift; | ||||
| 79 | my $ref = shift; | ||||
| 80 | |||||
| 81 | return overload::AddrRef($ref) | ||||
| 82 | if blessed $ref && $ref->isa('Exception::Class::Base'); | ||||
| 83 | |||||
| 84 | return overload::AddrRef($ref) unless $self->{respect_overload}; | ||||
| 85 | |||||
| 86 | local $@; | ||||
| 87 | local $SIG{__DIE__}; | ||||
| 88 | |||||
| 89 | my $str = eval { $ref . '' }; | ||||
| 90 | |||||
| 91 | return $@ ? overload::AddrRef($ref) : $str; | ||||
| 92 | } | ||||
| 93 | |||||
| 94 | sub _make_frames { | ||||
| 95 | my $self = shift; | ||||
| 96 | |||||
| 97 | my $filter = !$self->{filter_frames_early} && $self->_make_frame_filter(); | ||||
| 98 | |||||
| 99 | my $raw = delete $self->{raw}; | ||||
| 100 | for my $r ( @{$raw} ) { | ||||
| 101 | next if $filter && !$filter->($r); | ||||
| 102 | |||||
| 103 | $self->_add_frame( $r->{caller}, $r->{args} ); | ||||
| 104 | } | ||||
| 105 | } | ||||
| 106 | |||||
| 107 | 1 | 2µs | my $default_filter = sub { 1 }; | ||
| 108 | |||||
| 109 | sub _make_frame_filter { | ||||
| 110 | my $self = shift; | ||||
| 111 | |||||
| 112 | my ( @i_pack_re, %i_class ); | ||||
| 113 | if ( $self->{ignore_package} ) { | ||||
| 114 | local $@; | ||||
| 115 | local $SIG{__DIE__}; | ||||
| 116 | |||||
| 117 | $self->{ignore_package} = [ $self->{ignore_package} ] | ||||
| 118 | unless eval { @{ $self->{ignore_package} } }; | ||||
| 119 | |||||
| 120 | @i_pack_re | ||||
| 121 | = map { ref $_ ? $_ : qr/^\Q$_\E$/ } @{ $self->{ignore_package} }; | ||||
| 122 | } | ||||
| 123 | |||||
| 124 | my $p = __PACKAGE__; | ||||
| 125 | push @i_pack_re, qr/^\Q$p\E$/; | ||||
| 126 | |||||
| 127 | if ( $self->{ignore_class} ) { | ||||
| 128 | $self->{ignore_class} = [ $self->{ignore_class} ] | ||||
| 129 | unless ref $self->{ignore_class}; | ||||
| 130 | %i_class = map { $_ => 1 } @{ $self->{ignore_class} }; | ||||
| 131 | } | ||||
| 132 | |||||
| 133 | my $user_filter = $self->{frame_filter}; | ||||
| 134 | |||||
| 135 | return sub { | ||||
| 136 | return 0 if grep { $_[0]{caller}[0] =~ /$_/ } @i_pack_re; | ||||
| 137 | return 0 if grep { $_[0]{caller}[0]->isa($_) } keys %i_class; | ||||
| 138 | |||||
| 139 | if ($user_filter) { | ||||
| 140 | return $user_filter->( $_[0] ); | ||||
| 141 | } | ||||
| 142 | |||||
| 143 | return 1; | ||||
| 144 | }; | ||||
| 145 | } | ||||
| 146 | |||||
| 147 | sub _add_frame { | ||||
| 148 | my $self = shift; | ||||
| 149 | my $c = shift; | ||||
| 150 | my $p = shift; | ||||
| 151 | |||||
| 152 | # eval and is_require are only returned when applicable under 5.00503. | ||||
| 153 | push @$c, ( undef, undef ) if scalar @$c == 6; | ||||
| 154 | |||||
| 155 | push @{ $self->{frames} }, | ||||
| 156 | Devel::StackTrace::Frame->new( | ||||
| 157 | $c, | ||||
| 158 | $p, | ||||
| 159 | $self->{respect_overload}, | ||||
| 160 | $self->{max_arg_length}, | ||||
| 161 | $self->{message}, | ||||
| 162 | $self->{indent} | ||||
| 163 | ); | ||||
| 164 | } | ||||
| 165 | |||||
| 166 | sub next_frame { | ||||
| 167 | my $self = shift; | ||||
| 168 | |||||
| 169 | # reset to top if necessary. | ||||
| 170 | $self->{index} = -1 unless defined $self->{index}; | ||||
| 171 | |||||
| 172 | my @f = $self->frames(); | ||||
| 173 | if ( defined $f[ $self->{index} + 1 ] ) { | ||||
| 174 | return $f[ ++$self->{index} ]; | ||||
| 175 | } | ||||
| 176 | else { | ||||
| 177 | $self->{index} = undef; | ||||
| 178 | return undef; | ||||
| 179 | } | ||||
| 180 | } | ||||
| 181 | |||||
| 182 | sub prev_frame { | ||||
| 183 | my $self = shift; | ||||
| 184 | |||||
| 185 | my @f = $self->frames(); | ||||
| 186 | |||||
| 187 | # reset to top if necessary. | ||||
| 188 | $self->{index} = scalar @f unless defined $self->{index}; | ||||
| 189 | |||||
| 190 | if ( defined $f[ $self->{index} - 1 ] && $self->{index} >= 1 ) { | ||||
| 191 | return $f[ --$self->{index} ]; | ||||
| 192 | } | ||||
| 193 | else { | ||||
| 194 | $self->{index} = undef; | ||||
| 195 | return undef; | ||||
| 196 | } | ||||
| 197 | } | ||||
| 198 | |||||
| 199 | sub reset_pointer { | ||||
| 200 | my $self = shift; | ||||
| 201 | |||||
| 202 | $self->{index} = undef; | ||||
| 203 | } | ||||
| 204 | |||||
| 205 | sub frames { | ||||
| 206 | my $self = shift; | ||||
| 207 | |||||
| 208 | if (@_) { | ||||
| 209 | die | ||||
| 210 | "Devel::StackTrace->frames() can only take Devel::StackTrace::Frame args\n" | ||||
| 211 | if grep { !$_->isa('Devel::StackTrace::Frame') } @_; | ||||
| 212 | |||||
| 213 | $self->{frames} = \@_; | ||||
| 214 | } | ||||
| 215 | else { | ||||
| 216 | $self->_make_frames() if $self->{raw}; | ||||
| 217 | } | ||||
| 218 | |||||
| 219 | return @{ $self->{frames} }; | ||||
| 220 | } | ||||
| 221 | |||||
| 222 | sub frame { | ||||
| 223 | my $self = shift; | ||||
| 224 | my $i = shift; | ||||
| 225 | |||||
| 226 | return unless defined $i; | ||||
| 227 | |||||
| 228 | return ( $self->frames() )[$i]; | ||||
| 229 | } | ||||
| 230 | |||||
| 231 | sub frame_count { | ||||
| 232 | my $self = shift; | ||||
| 233 | |||||
| 234 | return scalar( $self->frames() ); | ||||
| 235 | } | ||||
| 236 | |||||
| 237 | sub as_string { | ||||
| 238 | my $self = shift; | ||||
| 239 | my $p = shift; | ||||
| 240 | |||||
| 241 | my $st = ''; | ||||
| 242 | my $first = 1; | ||||
| 243 | foreach my $f ( $self->frames() ) { | ||||
| 244 | $st .= $f->as_string( $first, $p ) . "\n"; | ||||
| 245 | $first = 0; | ||||
| 246 | } | ||||
| 247 | |||||
| 248 | return $st; | ||||
| 249 | } | ||||
| 250 | |||||
| 251 | { | ||||
| 252 | 1 | 300ns | package # hide from PAUSE | ||
| 253 | Devel::StackTraceFrame; | ||||
| 254 | |||||
| 255 | 1 | 6µs | our @ISA = 'Devel::StackTrace::Frame'; | ||
| 256 | } | ||||
| 257 | |||||
| 258 | 1 | 4µs | 1; | ||
| 259 | |||||
| 260 | # ABSTRACT: An object representing a stack trace | ||||
| 261 | |||||
| 262 | __END__ |