| Filename | /home/doy/perl5/perlbrew/perls/perl-5.10.1/lib/site_perl/5.10.1/Data/Visitor.pm |
| Statements | Executed 32 statements in 10.9ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2.21ms | 2.31ms | Data::Visitor::BEGIN@8 |
| 1 | 1 | 1 | 1.07ms | 1.79ms | Data::Visitor::BEGIN@10 |
| 1 | 1 | 1 | 69µs | 23.1ms | Data::Visitor::BEGIN@4 |
| 1 | 1 | 1 | 58µs | 120µs | Data::Visitor::BEGIN@370 |
| 1 | 1 | 1 | 49µs | 224µs | Data::Visitor::BEGIN@17 |
| 1 | 1 | 1 | 45µs | 315µs | Data::Visitor::BEGIN@6 |
| 1 | 1 | 1 | 43µs | 4.60ms | Data::Visitor::BEGIN@14 |
| 1 | 1 | 1 | 42µs | 110µs | Data::Visitor::BEGIN@12 |
| 1 | 1 | 1 | 20µs | 20µs | Data::Visitor::BEGIN@7 |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::_get_mapping |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::_print_trace |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::_register_mapping |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::retain_magic |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::trace |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_array |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_array_entries |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_array_entry |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_code |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_glob |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_hash |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_hash_entries |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_hash_entry |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_hash_key |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_hash_value |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_no_rec_check |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_normal_array |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_normal_glob |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_normal_hash |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_normal_scalar |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_object |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_ref |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_scalar |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_seen |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_tied |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_tied_array |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_tied_glob |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_tied_hash |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_tied_scalar |
| 0 | 0 | 0 | 0s | 0s | Data::Visitor::visit_value |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | #!/usr/bin/perl | ||||
| 2 | |||||
| 3 | package Data::Visitor; | ||||
| 4 | 3 | 242µs | 2 | 46.1ms | # spent 23.1ms (69µs+23.0) within Data::Visitor::BEGIN@4 which was called:
# once (69µs+23.0ms) by KiokuDB::Collapser::BEGIN@18 at line 4 # spent 23.1ms making 1 call to Data::Visitor::BEGIN@4
# spent 23.0ms making 1 call to Moose::Exporter::__ANON__[Moose/Exporter.pm:456] |
| 5 | |||||
| 6 | 3 | 110µs | 2 | 585µs | # spent 315µs (45+270) within Data::Visitor::BEGIN@6 which was called:
# once (45µs+270µs) by KiokuDB::Collapser::BEGIN@18 at line 6 # spent 315µs making 1 call to Data::Visitor::BEGIN@6
# spent 270µs making 1 call to Exporter::import |
| 7 | 3 | 77µs | 1 | 20µs | # spent 20µs within Data::Visitor::BEGIN@7 which was called:
# once (20µs+0s) by KiokuDB::Collapser::BEGIN@18 at line 7 # spent 20µs making 1 call to Data::Visitor::BEGIN@7 |
| 8 | 3 | 529µs | 1 | 2.31ms | # spent 2.31ms (2.21+102µs) within Data::Visitor::BEGIN@8 which was called:
# once (2.21ms+102µs) by KiokuDB::Collapser::BEGIN@18 at line 8 # spent 2.31ms making 1 call to Data::Visitor::BEGIN@8 |
| 9 | |||||
| 10 | 3 | 491µs | 1 | 1.79ms | # spent 1.79ms (1.07+723µs) within Data::Visitor::BEGIN@10 which was called:
# once (1.07ms+723µs) by KiokuDB::Collapser::BEGIN@18 at line 10 # spent 1.79ms making 1 call to Data::Visitor::BEGIN@10 |
| 11 | |||||
| 12 | 3 | 116µs | 2 | 178µs | # spent 110µs (42+68) within Data::Visitor::BEGIN@12 which was called:
# once (42µs+68µs) by KiokuDB::Collapser::BEGIN@18 at line 12 # spent 110µs making 1 call to Data::Visitor::BEGIN@12
# spent 68µs making 1 call to warnings::unimport |
| 13 | |||||
| 14 | 3 | 209µs | 2 | 9.16ms | # spent 4.60ms (43µs+4.56) within Data::Visitor::BEGIN@14 which was called:
# once (43µs+4.56ms) by KiokuDB::Collapser::BEGIN@18 at line 14 # spent 4.60ms making 1 call to Data::Visitor::BEGIN@14
# spent 4.56ms making 1 call to namespace::clean::import |
| 15 | |||||
| 16 | # the double not makes this no longer undef, so exempt from useless constant warnings in older perls | ||||
| 17 | 3 | 7.14ms | 2 | 399µs | # spent 224µs (49+175) within Data::Visitor::BEGIN@17 which was called:
# once (49µs+175µs) by KiokuDB::Collapser::BEGIN@18 at line 17 # spent 224µs making 1 call to Data::Visitor::BEGIN@17
# spent 175µs making 1 call to constant::import |
| 18 | |||||
| 19 | 1 | 4µs | our $VERSION = "0.27"; | ||
| 20 | |||||
| 21 | 1 | 12µs | 1 | 8.79ms | has tied_as_objects => ( # spent 8.79ms making 1 call to Moose::has |
| 22 | isa => "Bool", | ||||
| 23 | is => "rw", | ||||
| 24 | ); | ||||
| 25 | |||||
| 26 | # currently broken | ||||
| 27 | 1 | 15µs | 1 | 8.39ms | has weaken => ( # spent 8.39ms making 1 call to Moose::has |
| 28 | isa => "Bool", | ||||
| 29 | is => "rw", | ||||
| 30 | default => 0, | ||||
| 31 | ); | ||||
| 32 | |||||
| 33 | sub trace { | ||||
| 34 | my ( $self, $category, @msg ) = @_; | ||||
| 35 | |||||
| 36 | our %DEBUG; | ||||
| 37 | |||||
| 38 | if ( $DEBUG{$category} or !exists($DEBUG{$category}) ) { | ||||
| 39 | $self->_print_trace("$self: " . join("", | ||||
| 40 | ( " " x ( $self->{depth} - 1 ) ), | ||||
| 41 | ( join(" ", "$category:", map { overload::StrVal($_) } @msg) ), | ||||
| 42 | )); | ||||
| 43 | } | ||||
| 44 | } | ||||
| 45 | |||||
| 46 | sub _print_trace { | ||||
| 47 | my ( $self, @msg ) = @_; | ||||
| 48 | warn "@msg\n"; | ||||
| 49 | } | ||||
| 50 | |||||
| 51 | sub visit { | ||||
| 52 | my $self = shift; | ||||
| 53 | |||||
| 54 | local $self->{depth} = (($self->{depth}||0) + 1) if DEBUG; | ||||
| 55 | my $seen_hash = local $self->{_seen} = ($self->{_seen} || {}); # delete it after we're done with the whole visit | ||||
| 56 | |||||
| 57 | my @ret; | ||||
| 58 | |||||
| 59 | foreach my $data ( @_ ) { | ||||
| 60 | $self->trace( flow => visit => $data ) if DEBUG; | ||||
| 61 | |||||
| 62 | if ( my $refaddr = ref($data) && refaddr($data) ) { # only references need recursion checks | ||||
| 63 | $seen_hash->{weak} ||= isweak($data) if $self->weaken; | ||||
| 64 | |||||
| 65 | if ( exists $seen_hash->{$refaddr} ) { | ||||
| 66 | $self->trace( mapping => found_mapping => from => $data, to => $seen_hash->{$refaddr} ) if DEBUG; | ||||
| 67 | push @ret, $self->visit_seen( $data, $seen_hash->{$refaddr} ); | ||||
| 68 | next; | ||||
| 69 | } else { | ||||
| 70 | $self->trace( mapping => no_mapping => $data ) if DEBUG; | ||||
| 71 | } | ||||
| 72 | } | ||||
| 73 | |||||
| 74 | if ( defined wantarray ) { | ||||
| 75 | push @ret, scalar($self->visit_no_rec_check($data)); | ||||
| 76 | } else { | ||||
| 77 | $self->visit_no_rec_check($data); | ||||
| 78 | } | ||||
| 79 | } | ||||
| 80 | |||||
| 81 | return ( @_ == 1 ? $ret[0] : @ret ); | ||||
| 82 | } | ||||
| 83 | |||||
| 84 | sub visit_seen { | ||||
| 85 | my ( $self, $data, $result ) = @_; | ||||
| 86 | return $result; | ||||
| 87 | } | ||||
| 88 | |||||
| 89 | sub _get_mapping { | ||||
| 90 | my ( $self, $data ) = @_; | ||||
| 91 | $self->{_seen}{ refaddr($data) }; | ||||
| 92 | } | ||||
| 93 | |||||
| 94 | sub _register_mapping { | ||||
| 95 | my ( $self, $data, $new_data ) = @_; | ||||
| 96 | return $new_data unless ref $data; | ||||
| 97 | $self->trace( mapping => register_mapping => from => $data, to => $new_data, in => (caller(1))[3] ) if DEBUG; | ||||
| 98 | $self->{_seen}{ refaddr($data) } = $new_data; | ||||
| 99 | } | ||||
| 100 | |||||
| 101 | sub visit_no_rec_check { | ||||
| 102 | my ( $self, $data ) = @_; | ||||
| 103 | |||||
| 104 | if ( blessed($data) ) { | ||||
| 105 | return $self->visit_object($_[1]); | ||||
| 106 | } elsif ( ref $data ) { | ||||
| 107 | return $self->visit_ref($_[1]); | ||||
| 108 | } | ||||
| 109 | |||||
| 110 | return $self->visit_value($_[1]); | ||||
| 111 | } | ||||
| 112 | |||||
| 113 | sub visit_object { | ||||
| 114 | my ( $self, $object ) = @_; | ||||
| 115 | $self->trace( flow => visit_object => $object ) if DEBUG; | ||||
| 116 | |||||
| 117 | if ( not defined wantarray ) { | ||||
| 118 | $self->_register_mapping( $object, $object ); | ||||
| 119 | $self->visit_value($_[1]); | ||||
| 120 | return; | ||||
| 121 | } else { | ||||
| 122 | return $self->_register_mapping( $object, $self->visit_value($_[1]) ); | ||||
| 123 | } | ||||
| 124 | } | ||||
| 125 | |||||
| 126 | sub visit_ref { | ||||
| 127 | my ( $self, $data ) = @_; | ||||
| 128 | |||||
| 129 | local $self->{depth} = (($self->{depth}||0) + 1) if DEBUG; | ||||
| 130 | |||||
| 131 | $self->trace( flow => visit_ref => $data ) if DEBUG; | ||||
| 132 | |||||
| 133 | my $reftype = reftype $data; | ||||
| 134 | |||||
| 135 | $reftype = "SCALAR" if $reftype =~ /^(?:REF|LVALUE|VSTRING)$/; | ||||
| 136 | |||||
| 137 | my $method = $self->can(lc "visit_$reftype") || "visit_value"; | ||||
| 138 | |||||
| 139 | return $self->$method($_[1]); | ||||
| 140 | } | ||||
| 141 | |||||
| 142 | sub visit_value { | ||||
| 143 | my ( $self, $value ) = @_; | ||||
| 144 | $self->trace( flow => visit_value => $value ) if DEBUG; | ||||
| 145 | return $value; | ||||
| 146 | } | ||||
| 147 | |||||
| 148 | sub visit_hash { | ||||
| 149 | my ( $self, $hash ) = @_; | ||||
| 150 | |||||
| 151 | local $self->{depth} = (($self->{depth}||0) + 1) if DEBUG; | ||||
| 152 | |||||
| 153 | if ( defined(tied(%$hash)) and $self->tied_as_objects ) { | ||||
| 154 | return $self->visit_tied_hash(tied(%$hash), $_[1]); | ||||
| 155 | } else { | ||||
| 156 | return $self->visit_normal_hash($_[1]); | ||||
| 157 | } | ||||
| 158 | } | ||||
| 159 | |||||
| 160 | sub visit_normal_hash { | ||||
| 161 | my ( $self, $hash ) = @_; | ||||
| 162 | |||||
| 163 | if ( defined wantarray ) { | ||||
| 164 | my $new_hash = {}; | ||||
| 165 | $self->_register_mapping( $hash, $new_hash ); | ||||
| 166 | |||||
| 167 | %$new_hash = $self->visit_hash_entries($_[1]); | ||||
| 168 | |||||
| 169 | return $self->retain_magic( $_[1], $new_hash ); | ||||
| 170 | } else { | ||||
| 171 | $self->_register_mapping($hash, $hash); | ||||
| 172 | $self->visit_hash_entries($_[1]); | ||||
| 173 | return; | ||||
| 174 | } | ||||
| 175 | } | ||||
| 176 | |||||
| 177 | sub visit_tied_hash { | ||||
| 178 | my ( $self, $tied, $hash ) = @_; | ||||
| 179 | |||||
| 180 | if ( defined wantarray ) { | ||||
| 181 | my $new_hash = {}; | ||||
| 182 | $self->_register_mapping( $hash, $new_hash ); | ||||
| 183 | |||||
| 184 | if ( blessed(my $new_tied = $self->visit_tied($_[1], $_[2])) ) { | ||||
| 185 | $self->trace( data => tying => var => $new_hash, to => $new_tied ) if DEBUG; | ||||
| 186 | tie %$new_hash, 'Tie::ToObject', $new_tied; | ||||
| 187 | return $self->retain_magic($_[2], $new_hash); | ||||
| 188 | } else { | ||||
| 189 | return $self->visit_normal_hash($_[2]); | ||||
| 190 | } | ||||
| 191 | } else { | ||||
| 192 | $self->_register_mapping($hash, $hash); | ||||
| 193 | $self->visit_tied($_[1], $_[2]); | ||||
| 194 | return; | ||||
| 195 | } | ||||
| 196 | } | ||||
| 197 | |||||
| 198 | sub visit_hash_entries { | ||||
| 199 | my ( $self, $hash ) = @_; | ||||
| 200 | |||||
| 201 | if ( not defined wantarray ) { | ||||
| 202 | $self->visit_hash_entry( $_, $hash->{$_}, $hash ) for keys %$hash; | ||||
| 203 | } else { | ||||
| 204 | return map { $self->visit_hash_entry( $_, $hash->{$_}, $hash ) } keys %$hash; | ||||
| 205 | } | ||||
| 206 | } | ||||
| 207 | |||||
| 208 | sub visit_hash_entry { | ||||
| 209 | my ( $self, $key, $value, $hash ) = @_; | ||||
| 210 | |||||
| 211 | $self->trace( flow => visit_hash_entry => key => $key, value => $value ) if DEBUG; | ||||
| 212 | |||||
| 213 | if ( not defined wantarray ) { | ||||
| 214 | $self->visit_hash_key($key,$value,$hash); | ||||
| 215 | $self->visit_hash_value($_[2],$key,$hash); | ||||
| 216 | } else { | ||||
| 217 | return ( | ||||
| 218 | $self->visit_hash_key($key,$value,$hash), | ||||
| 219 | $self->visit_hash_value($_[2],$key,$hash), | ||||
| 220 | ); | ||||
| 221 | } | ||||
| 222 | } | ||||
| 223 | |||||
| 224 | sub visit_hash_key { | ||||
| 225 | my ( $self, $key, $value, $hash ) = @_; | ||||
| 226 | $self->visit($key); | ||||
| 227 | } | ||||
| 228 | |||||
| 229 | sub visit_hash_value { | ||||
| 230 | my ( $self, $value, $key, $hash ) = @_; | ||||
| 231 | $self->visit($_[1]); | ||||
| 232 | } | ||||
| 233 | |||||
| 234 | sub visit_array { | ||||
| 235 | my ( $self, $array ) = @_; | ||||
| 236 | |||||
| 237 | if ( defined(tied(@$array)) and $self->tied_as_objects ) { | ||||
| 238 | return $self->visit_tied_array(tied(@$array), $_[1]); | ||||
| 239 | } else { | ||||
| 240 | return $self->visit_normal_array($_[1]); | ||||
| 241 | } | ||||
| 242 | } | ||||
| 243 | |||||
| 244 | sub visit_normal_array { | ||||
| 245 | my ( $self, $array ) = @_; | ||||
| 246 | |||||
| 247 | if ( defined wantarray ) { | ||||
| 248 | my $new_array = []; | ||||
| 249 | $self->_register_mapping( $array, $new_array ); | ||||
| 250 | |||||
| 251 | @$new_array = $self->visit_array_entries($_[1]); | ||||
| 252 | |||||
| 253 | return $self->retain_magic( $_[1], $new_array ); | ||||
| 254 | } else { | ||||
| 255 | $self->_register_mapping( $array, $array ); | ||||
| 256 | $self->visit_array_entries($_[1]); | ||||
| 257 | |||||
| 258 | return; | ||||
| 259 | } | ||||
| 260 | } | ||||
| 261 | |||||
| 262 | sub visit_tied_array { | ||||
| 263 | my ( $self, $tied, $array ) = @_; | ||||
| 264 | |||||
| 265 | if ( defined wantarray ) { | ||||
| 266 | my $new_array = []; | ||||
| 267 | $self->_register_mapping( $array, $new_array ); | ||||
| 268 | |||||
| 269 | if ( blessed(my $new_tied = $self->visit_tied($_[1], $_[2])) ) { | ||||
| 270 | $self->trace( data => tying => var => $new_array, to => $new_tied ) if DEBUG; | ||||
| 271 | tie @$new_array, 'Tie::ToObject', $new_tied; | ||||
| 272 | return $self->retain_magic($_[2], $new_array); | ||||
| 273 | } else { | ||||
| 274 | return $self->visit_normal_array($_[2]); | ||||
| 275 | } | ||||
| 276 | } else { | ||||
| 277 | $self->_register_mapping( $array, $array ); | ||||
| 278 | $self->visit_tied($_[1], $_[2]); | ||||
| 279 | |||||
| 280 | return; | ||||
| 281 | } | ||||
| 282 | } | ||||
| 283 | |||||
| 284 | sub visit_array_entries { | ||||
| 285 | my ( $self, $array ) = @_; | ||||
| 286 | |||||
| 287 | if ( not defined wantarray ) { | ||||
| 288 | $self->visit_array_entry( $array->[$_], $_, $array ) for 0 .. $#$array; | ||||
| 289 | } else { | ||||
| 290 | return map { $self->visit_array_entry( $array->[$_], $_, $array ) } 0 .. $#$array; | ||||
| 291 | } | ||||
| 292 | } | ||||
| 293 | |||||
| 294 | sub visit_array_entry { | ||||
| 295 | my ( $self, $value, $index, $array ) = @_; | ||||
| 296 | $self->visit($_[1]); | ||||
| 297 | } | ||||
| 298 | |||||
| 299 | sub visit_scalar { | ||||
| 300 | my ( $self, $scalar ) = @_; | ||||
| 301 | |||||
| 302 | if ( defined(tied($$scalar)) and $self->tied_as_objects ) { | ||||
| 303 | return $self->visit_tied_scalar(tied($$scalar), $_[1]); | ||||
| 304 | } else { | ||||
| 305 | return $self->visit_normal_scalar($_[1]); | ||||
| 306 | } | ||||
| 307 | } | ||||
| 308 | |||||
| 309 | sub visit_normal_scalar { | ||||
| 310 | my ( $self, $scalar ) = @_; | ||||
| 311 | |||||
| 312 | if ( defined wantarray ) { | ||||
| 313 | my $new_scalar; | ||||
| 314 | $self->_register_mapping( $scalar, \$new_scalar ); | ||||
| 315 | |||||
| 316 | $new_scalar = $self->visit( $$scalar ); | ||||
| 317 | |||||
| 318 | return $self->retain_magic($_[1], \$new_scalar); | ||||
| 319 | } else { | ||||
| 320 | $self->_register_mapping( $scalar, $scalar ); | ||||
| 321 | $self->visit( $$scalar ); | ||||
| 322 | return; | ||||
| 323 | } | ||||
| 324 | |||||
| 325 | } | ||||
| 326 | |||||
| 327 | sub visit_tied_scalar { | ||||
| 328 | my ( $self, $tied, $scalar ) = @_; | ||||
| 329 | |||||
| 330 | if ( defined wantarray ) { | ||||
| 331 | my $new_scalar; | ||||
| 332 | $self->_register_mapping( $scalar, \$new_scalar ); | ||||
| 333 | |||||
| 334 | if ( blessed(my $new_tied = $self->visit_tied($_[1], $_[2])) ) { | ||||
| 335 | $self->trace( data => tying => var => $new_scalar, to => $new_tied ) if DEBUG; | ||||
| 336 | tie $new_scalar, 'Tie::ToObject', $new_tied; | ||||
| 337 | return $self->retain_magic($_[2], \$new_scalar); | ||||
| 338 | } else { | ||||
| 339 | return $self->visit_normal_scalar($_[2]); | ||||
| 340 | } | ||||
| 341 | } else { | ||||
| 342 | $self->_register_mapping( $scalar, $scalar ); | ||||
| 343 | $self->visit_tied($_[1], $_[2]); | ||||
| 344 | return; | ||||
| 345 | } | ||||
| 346 | } | ||||
| 347 | |||||
| 348 | sub visit_code { | ||||
| 349 | my ( $self, $code ) = @_; | ||||
| 350 | $self->visit_value($_[1]); | ||||
| 351 | } | ||||
| 352 | |||||
| 353 | sub visit_glob { | ||||
| 354 | my ( $self, $glob ) = @_; | ||||
| 355 | |||||
| 356 | if ( defined(tied(*$glob)) and $self->tied_as_objects ) { | ||||
| 357 | return $self->visit_tied_glob(tied(*$glob), $_[1]); | ||||
| 358 | } else { | ||||
| 359 | return $self->visit_normal_glob($_[1]); | ||||
| 360 | } | ||||
| 361 | } | ||||
| 362 | |||||
| 363 | sub visit_normal_glob { | ||||
| 364 | my ( $self, $glob ) = @_; | ||||
| 365 | |||||
| 366 | if ( defined wantarray ) { | ||||
| 367 | my $new_glob = Symbol::gensym(); | ||||
| 368 | $self->_register_mapping( $glob, $new_glob ); | ||||
| 369 | |||||
| 370 | 3 | 1.80ms | 2 | 183µs | # spent 120µs (58+63) within Data::Visitor::BEGIN@370 which was called:
# once (58µs+63µs) by KiokuDB::Collapser::BEGIN@18 at line 370 # spent 120µs making 1 call to Data::Visitor::BEGIN@370
# spent 62µs making 1 call to warnings::unimport |
| 371 | *$new_glob = $self->visit( *$glob{$_} || next ) for qw/SCALAR ARRAY HASH/; | ||||
| 372 | |||||
| 373 | return $self->retain_magic($_[1], $new_glob); | ||||
| 374 | } else { | ||||
| 375 | $self->_register_mapping( $glob, $glob ); | ||||
| 376 | $self->visit( *$glob{$_} || next ) for qw/SCALAR ARRAY HASH/; | ||||
| 377 | return; | ||||
| 378 | } | ||||
| 379 | } | ||||
| 380 | |||||
| 381 | sub visit_tied_glob { | ||||
| 382 | my ( $self, $tied, $glob ) = @_; | ||||
| 383 | |||||
| 384 | if ( defined wantarray ) { | ||||
| 385 | my $new_glob = Symbol::gensym(); | ||||
| 386 | $self->_register_mapping( $glob, \$new_glob ); | ||||
| 387 | |||||
| 388 | if ( blessed(my $new_tied = $self->visit_tied($_[1], $_[2])) ) { | ||||
| 389 | $self->trace( data => tying => var => $new_glob, to => $new_tied ) if DEBUG; | ||||
| 390 | tie *$new_glob, 'Tie::ToObject', $new_tied; | ||||
| 391 | return $self->retain_magic($_[2], $new_glob); | ||||
| 392 | } else { | ||||
| 393 | return $self->visit_normal_glob($_[2]); | ||||
| 394 | } | ||||
| 395 | } else { | ||||
| 396 | $self->_register_mapping( $glob, $glob ); | ||||
| 397 | $self->visit_tied($_[1], $_[2]); | ||||
| 398 | return; | ||||
| 399 | } | ||||
| 400 | } | ||||
| 401 | |||||
| 402 | sub retain_magic { | ||||
| 403 | my ( $self, $proto, $new ) = @_; | ||||
| 404 | |||||
| 405 | if ( blessed($proto) and !blessed($new) ) { | ||||
| 406 | $self->trace( data => blessing => $new, ref $proto ) if DEBUG; | ||||
| 407 | bless $new, ref $proto; | ||||
| 408 | } | ||||
| 409 | |||||
| 410 | my $seen_hash = $self->{_seen}; | ||||
| 411 | if ( $seen_hash->{weak} ) { | ||||
| 412 | require Data::Alias; | ||||
| 413 | |||||
| 414 | my @weak_refs; | ||||
| 415 | foreach my $value ( Data::Alias::deref($proto) ) { | ||||
| 416 | if ( ref $value and isweak($value) ) { | ||||
| 417 | push @weak_refs, refaddr $value; | ||||
| 418 | } | ||||
| 419 | } | ||||
| 420 | |||||
| 421 | if ( @weak_refs ) { | ||||
| 422 | my %targets = map { refaddr($_) => 1 } @{ $self->{_seen} }{@weak_refs}; | ||||
| 423 | foreach my $value ( Data::Alias::deref($new) ) { | ||||
| 424 | if ( ref $value and $targets{refaddr($value)}) { | ||||
| 425 | push @{ $seen_hash->{weakened} ||= [] }, $value; # keep a ref around | ||||
| 426 | weaken($value); | ||||
| 427 | } | ||||
| 428 | } | ||||
| 429 | } | ||||
| 430 | } | ||||
| 431 | |||||
| 432 | # FIXME real magic, too | ||||
| 433 | |||||
| 434 | return $new; | ||||
| 435 | } | ||||
| 436 | |||||
| 437 | sub visit_tied { | ||||
| 438 | my ( $self, $tied, $var ) = @_; | ||||
| 439 | $self->trace( flow => visit_tied => $tied ) if DEBUG; | ||||
| 440 | $self->visit($_[1]); # as an object eventually | ||||
| 441 | } | ||||
| 442 | |||||
| 443 | 1 | 53µs | 4 | 13.3ms | __PACKAGE__->meta->make_immutable if __PACKAGE__->meta->can("make_immutable"); # spent 13.2ms making 1 call to Class::MOP::Class::make_immutable
# spent 165µs making 2 calls to Data::Visitor::meta, avg 82µs/call
# spent 7µs making 1 call to UNIVERSAL::can |
| 444 | |||||
| 445 | 1 | 57µs | __PACKAGE__ | ||
| 446 | |||||
| 447 | 1 | 56µs | 1 | 14.2ms | __END__ # spent 14.2ms making 1 call to B::Hooks::EndOfScope::__ANON__[B/Hooks/EndOfScope.pm:26] |