File Coverage

blib/lib/Devel/MAT/SV.pm
Criterion Covered Total %
statement 790 1099 71.8
branch 282 482 58.5
condition 72 146 49.3
subroutine 192 276 69.5
pod 17 23 73.9
total 1353 2026 66.7


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2013-2022 -- leonerd@leonerd.org.uk
5              
6             package Devel::MAT::SV 0.50;
7              
8 9     9   108 use v5.14;
  9         31  
9 9     9   46 use warnings;
  9         22  
  9         218  
10              
11 9     9   43 use Carp;
  9         14  
  9         468  
12 9     9   49 use Scalar::Util qw( weaken );
  9         24  
  9         378  
13              
14 9     9   603 use Syntax::Keyword::Match;
  9         1852  
  9         78  
15              
16             # Load XS code
17             require Devel::MAT;
18              
19 9     9   574 use constant immortal => 0;
  9         29  
  9         1065  
20              
21 9     9   68 use List::Util qw( first );
  9         36  
  9         612  
22              
23 9     9   4505 use Struct::Dumb 0.07 qw( readonly_struct );
  9         24064  
  9         52  
24             readonly_struct Reference => [qw( name strength sv )];
25             readonly_struct Magic => [qw( type obj ptr vtbl )];
26              
27             =head1 NAME
28              
29             C - represent a single SV from a heap dump
30              
31             =head1 DESCRIPTION
32              
33             Objects in this class represent individual SV variables found in the arena
34             during a heap dump. Actual types of SV are represented by subclasses, which
35             are documented below.
36              
37             =cut
38              
39             my $CONSTANTS;
40             BEGIN {
41 9     9   1360 $CONSTANTS = {
42             STRENGTH_STRONG => (1 << 0),
43             STRENGTH_WEAK => (1 << 1),
44             STRENGTH_INDIRECT => (1 << 2),
45             STRENGTH_INFERRED => (1 << 3),
46             };
47 9         29 $CONSTANTS->{STRENGTH_DIRECT} = $CONSTANTS->{STRENGTH_STRONG}|$CONSTANTS->{STRENGTH_WEAK};
48 9         195 $CONSTANTS->{STRENGTH_ALL} = $CONSTANTS->{STRENGTH_STRONG}|$CONSTANTS->{STRENGTH_WEAK}|$CONSTANTS->{STRENGTH_INDIRECT}|$CONSTANTS->{STRENGTH_INFERRED};
49             }
50 9     9   218 use constant $CONSTANTS;
  9         30  
  9         1488  
51              
52             my %types;
53             sub register_type
54             {
55 171     171 0 562 $types{$_[1]} = $_[0];
56             # generate the ->type constant method
57 171         565 ( my $typename = $_[0] ) =~ s/^Devel::MAT::SV:://;
58 9     9   84 no strict 'refs';
  9         18  
  9         17265  
59 171 100   0   349 *{"$_[0]::type"} = sub () { $typename } unless defined *{"$_[0]::type"}{CODE};
  162         567  
  0         0  
  171         1548  
60             }
61              
62             sub new
63             {
64 573408     573408 0 838486 shift;
65 573408         993886 my ( $type, $df, $header, $ptrs, $strs ) = @_;
66              
67 573408 50       1277704 my $class = $types{$type} or croak "Cannot load unknown SV type $type";
68              
69 573408         1079858 my $self = bless {}, $class;
70              
71 573408         3164819 $self->_set_core_fields(
72             $type, $df,
73             ( unpack "$df->{ptr_fmt} $df->{u32_fmt} $df->{uint_fmt}", $header ),
74             $ptrs->[0],
75             );
76              
77 573408         1308009 return $self;
78             }
79              
80             =head1 COMMON METHODS
81              
82             =cut
83              
84             =head2 type
85              
86             $type = $sv->type
87              
88             Returns the major type of the SV. This is the class name minus the
89             C prefix.
90              
91             =cut
92              
93             =head2 basetype
94              
95             $type = $sv->basetype
96              
97             Returns the inner perl API type of the SV. This is one of
98              
99             SV AV HV CV GV LV PVIO PVFM REGEXP INVLIST OBJ
100              
101             =head2 desc
102              
103             $desc = $sv->desc
104              
105             Returns a string describing the type of the SV and giving a short detail of
106             its contents. The exact details depends on the SV type.
107              
108             =cut
109              
110             =head2 desc_addr
111              
112             $desc = $sv->desc_addr
113              
114             Returns a string describing the SV as with C and giving its address in
115             hex. A useful way to uniquely identify the SV when printing.
116              
117             =cut
118              
119             sub desc_addr
120             {
121 0     0 1 0 my $self = shift;
122 0         0 return sprintf "%s at %#x", $self->desc, $self->addr;
123             }
124              
125             =head2 addr
126              
127             $addr = $sv->addr
128              
129             Returns the address of the SV
130              
131             =cut
132              
133             # XS accessor
134              
135             =head2 refcnt
136              
137             $count = $sv->refcnt
138              
139             Returns the C reference count of the SV
140              
141             =head2 refcount_adjusted
142              
143             $count = $sv->refcount_adjusted
144              
145             Returns the reference count of the SV, adjusted to take account of the fact
146             that the C value of the backrefs list of a hash or weakly-referenced
147             object is artificially high.
148              
149             =cut
150              
151             # XS accessor
152              
153 0     0 1 0 sub refcount_adjusted { shift->refcnt }
154              
155             =head2 blessed
156              
157             $stash = $sv->blessed
158              
159             If the SV represents a blessed object, returns the stash SV. Otherwise returns
160             C.
161              
162             =cut
163              
164             sub blessed
165             {
166 180859     180859 1 241081 my $self = shift;
167 180859         547059 return $self->df->sv_at( $self->blessed_at );
168             }
169              
170             =head2 symname
171              
172             $name = $sv->symname
173              
174             Called on an SV which is a member of the symbol table, this method returns the
175             perl representation of the full symbol name, including sigil. Otherwise,
176             returns C.
177              
178             A leading C prefix is removed for symbols in packages other than
179             C
.
180              
181             =cut
182              
183             my $mksymname = sub {
184             my ( $sigil, $glob ) = @_;
185              
186             my $stashname = $glob->stashname;
187             $stashname =~ s/^main::// if $stashname =~ m/^main::.+::/;
188             return $sigil . $stashname;
189             };
190              
191       0 1   sub symname {}
192              
193             =head2 size
194              
195             $size = $sv->size
196              
197             Returns the (approximate) size in bytes of the SV
198              
199             =cut
200              
201             # XS accessor
202              
203             =head2 magic
204              
205             @magics = $sv->magic
206              
207             Returns a list of magic applied to the SV; each giving the type and target SVs
208             as struct fields:
209              
210             $type = $magic->type
211             $sv = $magic->obj
212             $sv = $magic->ptr
213             $ptr = $magic->vtbl
214              
215             =cut
216              
217             sub magic
218             {
219 0     0 1 0 my $self = shift;
220 0 0       0 return unless my $magic = $self->{magic};
221              
222 0         0 my $df = $self->df;
223             return map {
224 0         0 my ( $type, undef, $obj_at, $ptr_at, $vtbl_ptr ) = @$_;
  0         0  
225 0         0 Magic( $type, $df->sv_at( $obj_at ), $df->sv_at( $ptr_at ), $vtbl_ptr );
226             } @$magic;
227             }
228              
229             =head2 magic_svs
230              
231             @svs = $sv->magic_svs
232              
233             A more efficient way to retrieve just the SVs associated with the applied
234             magic.
235              
236             =cut
237              
238             sub magic_svs
239             {
240 29476     29476 1 37761 my $self = shift;
241 29476 100       176734 return unless my $magic = $self->{magic};
242              
243 481         1129 my $df = $self->df;
244             return map {
245 481         1104 my ( undef, undef, $obj_at, $ptr_at ) = @$_;
  481         1204  
246 481 100       1318 ( $obj_at ? ( $df->sv_at( $obj_at ) ) : () ),
    100          
247             ( $ptr_at ? ( $df->sv_at( $ptr_at ) ) : () )
248             } @$magic;
249             }
250              
251             =head2 backrefs
252              
253             $av_or_rv = $sv->backrefs
254              
255             Returns backrefs SV, which may be an AV containing the back references, or
256             if there is only one, the REF SV itself referring to this.
257              
258             =cut
259              
260             sub backrefs
261             {
262 1     1 1 12 my $self = shift;
263              
264 1 50       6 return undef unless my $magic = $self->{magic};
265              
266 1         4 foreach my $mg ( @$magic ) {
267 1         4 my ( $type, undef, $obj_at ) = @$mg;
268             # backrefs list uses "<" magic type
269 1 50       9 return $self->df->sv_at( $obj_at ) if $type eq "<";
270             }
271              
272 0         0 return undef;
273             }
274              
275             =head2 rootname
276              
277             $rootname = $sv->rootname
278              
279             If the SV is a well-known root, this method returns its name. Otherwise
280             returns C.
281              
282             =cut
283              
284             sub rootname
285             {
286 4     4 1 9 my $self = shift;
287 4         17 return $self->{rootname};
288             }
289              
290             # internal
291             sub more_magic
292             {
293 41864     41864 0 60935 my $self = shift;
294 41864         72151 my ( $type, $flags, $obj_at, $ptr_at, $vtbl_ptr ) = @_;
295              
296 41864         55469 push @{ $self->{magic} }, [ $type => $flags, $obj_at, $ptr_at, $vtbl_ptr ];
  41864         192045  
297             }
298              
299             sub _more_annotations
300             {
301 0     0   0 my $self = shift;
302 0         0 my ( $val_at, $name ) = @_;
303              
304 0         0 push @{ $self->{annotations} }, [ $val_at, $name ];
  0         0  
305             }
306              
307             # DEBUG_LEAKING_SCALARS
308             sub _debugdata
309             {
310 0     0   0 my $self = shift;
311 0         0 my ( $serial, $line, $file ) = @_;
312 0         0 $self->{debugdata} = [ $serial, $line, $file ];
313             }
314              
315             sub debug_serial
316             {
317 0     0 0 0 my $self = shift;
318 0   0     0 return $self->{debugdata} && $self->{debugdata}[0];
319             }
320              
321             sub debug_line
322             {
323 0     0 0 0 my $self = shift;
324 0   0     0 return $self->{debugdata} && $self->{debugdata}[1];
325             }
326              
327             sub debug_file
328             {
329 0     0 0 0 my $self = shift;
330 0   0     0 return $self->{debugdata} && $self->{debugdata}[2];
331             }
332              
333             =head2 outrefs
334              
335             @refs = $sv->outrefs
336              
337             Returns a list of Reference objects for each of the SVs that this one refers
338             to, either directly by strong or weak reference, indirectly via RV, or
339             inferred by C itself.
340              
341             Each object is a structure of three fields:
342              
343             =over 4
344              
345             =item name => STRING
346              
347             A human-readable string for identification purposes.
348              
349             =item strength => "strong"|"weak"|"indirect"|"inferred"
350              
351             Identifies what kind of reference it is. C references contribute to
352             the C of the referrant, others do not. C and C
353             references are SV addresses found directly within the referring SV structure;
354             C and C references are extra return values added here for
355             convenience by examining the surrounding structure.
356              
357             =item sv => SV
358              
359             The referrant SV itself.
360              
361             =back
362              
363             =cut
364              
365             sub _outrefs_matching
366             {
367 180870     180870   260426 my $self = shift;
368 180870         310697 my ( $match, $no_desc ) = @_;
369              
370             # In scalar context we're just counting so we might as well count just SVs
371 180870   66     339629 $no_desc ||= !wantarray;
372              
373 180870         372091 my @outrefs = $self->_outrefs( $match, $no_desc );
374              
375 180870 100 100     493874 if( $match & STRENGTH_WEAK and my $blessed = $self->blessed ) {
376 1407 100       3643 push @outrefs, $no_desc ? ( weak => $blessed ) :
377             Reference( "the bless package", weak => $blessed );
378             }
379              
380 180870 100       261373 foreach my $mg ( @{ $self->{magic} || [] } ) {
  180870         698423  
381 17030         79054 my ( $type, $flags, $obj_at, $ptr_at ) = @$mg;
382              
383 17030 100       45892 if( my $obj = $self->df->sv_at( $obj_at ) ) {
384 15379         28396 my $is_strong = ( $flags & 0x01 );
385 15379 100       43372 if( $match & ( $is_strong ? STRENGTH_STRONG : STRENGTH_WEAK ) ) {
    50          
386 15379 100       31949 my $strength = $is_strong ? "strong" : "weak";
387 15379 100       43298 push @outrefs, $no_desc ? ( $strength => $obj ) :
388             Reference( "'$type' magic object", $strength => $obj );
389             }
390             }
391              
392 17030 100 66     94794 if( $match & STRENGTH_STRONG and my $ptr = $self->df->sv_at( $ptr_at ) ) {
393 4 50       23 push @outrefs, $no_desc ? ( strong => $ptr ) :
394             Reference( "'$type' magic pointer", strong => $ptr );
395             }
396             }
397              
398 180870 50       261486 foreach my $ann ( @{ $self->{annotations} || [] } ) {
  180870         509283  
399 0         0 my ( $val_at, $name ) = @$ann;
400 0 0       0 my $val = $self->df->sv_at( $val_at ) or next;
401              
402 0 0       0 push @outrefs, $no_desc ? ( strong => $val ) :
403             Reference( $name, strong => $val );
404             }
405              
406 180870 50       341247 return @outrefs / 2 if !wantarray;
407 180870         1460874 return @outrefs;
408             }
409              
410 180854     180854 1 366078 sub outrefs { $_[0]->_outrefs_matching( STRENGTH_ALL, $_[1] ) }
411              
412             =head2 outrefs_strong
413              
414             @refs = $sv->outrefs_strong
415              
416             Returns the subset of C that are direct strong references.
417              
418             =head2 outrefs_weak
419              
420             @refs = $sv->outrefs_weak
421              
422             Returns the subset of C that are direct weak references.
423              
424             =head2 outrefs_direct
425              
426             @refs = $sv->outrefs_direct
427              
428             Returns the subset of C that are direct strong or weak references.
429              
430             =head2 outrefs_indirect
431              
432             @refs = $sv->outrefs_indirect
433              
434             Returns the subset of C that are indirect references via RVs.
435              
436             =head2 outrefs_inferred
437              
438             @refs = $sv->outrefs_inferred
439              
440             Returns the subset of C that are not directly stored in the SV
441             structure, but instead inferred by C itself.
442              
443             =cut
444              
445 14     14 1 44 sub outrefs_strong { $_[0]->_outrefs_matching( STRENGTH_STRONG, $_[1] ) }
446 0     0 1 0 sub outrefs_weak { $_[0]->_outrefs_matching( STRENGTH_WEAK, $_[1] ) }
447 1     1 1 84 sub outrefs_direct { $_[0]->_outrefs_matching( STRENGTH_DIRECT, $_[1] ) }
448 1     1 1 2544 sub outrefs_indirect { $_[0]->_outrefs_matching( STRENGTH_INDIRECT, $_[1] ) }
449 0     0 1 0 sub outrefs_inferred { $_[0]->_outrefs_matching( STRENGTH_INFERRED, $_[1] ) }
450              
451             =head2 outref_named
452              
453             $ref = $sv->outref_named( $name )
454              
455             I
456              
457             Looks for a reference whose name is exactly that given, and returns it if so.
458              
459             Throws an exception if the SV has no such outref of that name.
460              
461             =head2 maybe_outref_named
462              
463             $ref = $sv->maybe_outref_named( $name )
464              
465             I
466              
467             As L but returns C if there is no such reference.
468              
469             =cut
470              
471             sub maybe_outref_named
472             {
473 2     2 1 709 my $self = shift;
474 2         4 my ( $name ) = @_;
475              
476 2     3   16 return first { $_->name eq $name } $self->outrefs;
  3         14  
477             }
478              
479             sub outref_named
480             {
481 1     1 1 2550 my $self = shift;
482 1         3 my ( $name ) = @_;
483              
484 1   33     7 return $self->maybe_outref_named( $name ) // croak "No outref named $name";
485             }
486              
487             =head2 is_mortal
488              
489             $mortal = $sv->is_mortal
490              
491             Returns true if this SV is referenced by the temps stack.
492              
493             =cut
494              
495             sub _set_is_mortal
496             {
497 0     0   0 my $self = shift;
498 0         0 $self->{is_mortal} = 1;
499             }
500              
501             sub is_mortal
502             {
503 3384     3384 1 8223 my $self = shift;
504 3384         14583 return $self->{is_mortal};
505             }
506              
507             =head1 IMMORTAL SVs
508              
509             Three special SV objects exist outside of the heap, to represent C and
510             boolean true and false. They are
511              
512             =over 4
513              
514             =item * Devel::MAT::SV::UNDEF
515              
516             =item * Devel::MAT::SV::YES
517              
518             =item * Devel::MAT::SV::NO
519              
520             =back
521              
522             =cut
523              
524             package Devel::MAT::SV::Immortal 0.50;
525 9     9   81 use base qw( Devel::MAT::SV );
  9         18  
  9         1320  
526 9     9   67 use constant immortal => 1;
  9         56  
  9         619  
527 9     9   57 use constant basetype => "SV";
  9         30  
  9         1383  
528             sub new {
529 21     21   47 my $class = shift;
530 21         42 my ( $df, $addr ) = @_;
531 21         45 my $self = bless {}, $class;
532 21         192 $self->_set_core_fields( 0, $df, $addr, 0, 0, 0 );
533 21         83 return $self;
534             }
535 3     3   9 sub _outrefs { () }
536              
537             package Devel::MAT::SV::UNDEF 0.50;
538 9     9   89 use base qw( Devel::MAT::SV::Immortal );
  9         19  
  9         3630  
539 0     0   0 sub desc { "UNDEF" }
540 1662     1662   5530 sub type { "UNDEF" }
541              
542             package Devel::MAT::SV::YES 0.50;
543 9     9   68 use base qw( Devel::MAT::SV::Immortal );
  9         27  
  9         3643  
544 0     0   0 sub desc { "YES" }
545 993     993   3141 sub type { "SCALAR" }
546              
547             # Pretend to be 1 / "1"
548 0     0   0 sub uv { 1 }
549 0     0   0 sub iv { 1 }
550 0     0   0 sub nv { 1.0 }
551 0     0   0 sub pv { "1" }
552 0     0   0 sub rv { undef }
553 0     0   0 sub is_weak { '' }
554              
555             package Devel::MAT::SV::NO 0.50;
556 9     9   64 use base qw( Devel::MAT::SV::Immortal );
  9         20  
  9         3469  
557 0     0   0 sub desc { "NO" }
558 0     0   0 sub type { "SCALAR" }
559              
560             # Pretend to be 0 / ""
561 0     0   0 sub uv { 0 }
562 0     0   0 sub iv { 0 }
563 0     0   0 sub nv { 0.0 }
564 0     0   0 sub pv { "0" }
565 0     0   0 sub rv { undef }
566 0     0   0 sub is_weak { '' }
567              
568             package Devel::MAT::SV::Unknown 0.50;
569 9     9   75 use base qw( Devel::MAT::SV );
  9         25  
  9         1383  
570             __PACKAGE__->register_type( 0xff );
571              
572 0     0   0 sub desc { "UNKNOWN" }
573              
574       0     sub _outrefs {}
575              
576             package Devel::MAT::SV::GLOB 0.50;
577 9     9   65 use base qw( Devel::MAT::SV );
  9         15  
  9         830  
578             __PACKAGE__->register_type( 1 );
579 9     9   57 use constant $CONSTANTS;
  9         38  
  9         903  
580 9     9   61 use constant basetype => "GV";
  9         18  
  9         9896  
581              
582             =head1 Devel::MAT::SV::GLOB
583              
584             Represents a glob; an SV of type C.
585              
586             =cut
587              
588             sub load
589             {
590 53848     53848   87297 my $self = shift;
591 53848         90276 my ( $header, $ptrs, $strs ) = @_;
592 53848         112693 my $df = $self->df;
593              
594 53848         119072 my ( $line ) =
595             unpack "$df->{uint_fmt}", $header;
596              
597             $self->_set_glob_fields(
598 53848         86095 @{$ptrs}[0..7],
  53848         277279  
599             $line, $strs->[1],
600             $strs->[0],
601             );
602             }
603              
604             sub _fixup
605             {
606 53848     53848   71205 my $self = shift;
607              
608 53848   66     82238 $_ and $_->_set_glob_at( $self->addr ) for $self->scalar, $self->array, $self->hash, $self->code;
609             }
610              
611             =head2 file
612              
613             =head2 line
614              
615             =head2 location
616              
617             $file = $gv->file
618              
619             $line = $gv->line
620              
621             $location = $gv->location
622              
623             Returns the filename, line number, or combined location (C)
624             that the GV first appears at.
625              
626             =head2 name
627              
628             $name = $gv->name
629              
630             Returns the value of the C field, for named globs.
631              
632             =cut
633              
634             # XS accessors
635              
636             sub location
637             {
638 0     0   0 my $self = shift;
639 0         0 my $file = $self->file;
640 0         0 my $line = $self->line;
641 0 0       0 defined $file ? "$file line $line" : undef
642             }
643              
644             =head2 stash
645              
646             $stash = $gv->stash
647              
648             Returns the stash to which the GV belongs.
649              
650             =cut
651              
652 27     27   40 sub stash { my $self = shift; $self->df->sv_at( $self->stash_at ) }
  27         112  
653              
654             =head2 scalar
655              
656             =head2 array
657              
658             =head2 hash
659              
660             =head2 code
661              
662             =head2 egv
663              
664             =head2 io
665              
666             =head2 form
667              
668             $sv = $gv->scalar
669              
670             $av = $gv->array
671              
672             $hv = $gv->hash
673              
674             $cv = $gv->code
675              
676             $gv = $gv->egv
677              
678             $io = $gv->io
679              
680             $form = $gv->form
681              
682             Return the SV in the various glob slots.
683              
684             =cut
685              
686 97007     97007   128381 sub scalar { my $self = shift; $self->df->sv_at( $self->scalar_at ) }
  97007         411902  
687 97002     97002   136267 sub array { my $self = shift; $self->df->sv_at( $self->array_at ) }
  97002         258143  
688 97346     97346   131206 sub hash { my $self = shift; $self->df->sv_at( $self->hash_at ) }
  97346         251589  
689 97007     97007   135076 sub code { my $self = shift; $self->df->sv_at( $self->code_at ) }
  97007         250869  
690 35808     35808   47255 sub egv { my $self = shift; $self->df->sv_at( $self->egv_at ) }
  35808         102320  
691 43148     43148   60659 sub io { my $self = shift; $self->df->sv_at( $self->io_at ) }
  43148         118894  
692 43147     43147   61939 sub form { my $self = shift; $self->df->sv_at( $self->form_at ) }
  43147         120173  
693              
694             sub stashname
695             {
696 27     27   46 my $self = shift;
697 27         71 my $name = $self->name;
698 27         97 $name =~ s(^([\x00-\x1f])){"^" . chr(64 + ord $1)}e;
  0         0  
699 27         96 return $self->stash->stashname . "::" . $name;
700             }
701              
702             sub desc
703             {
704 15386     15386   73107 my $self = shift;
705 15386         19567 my $sigils = "";
706 15386 100       24053 $sigils .= '$' if $self->scalar;
707 15386 100       26995 $sigils .= '@' if $self->array;
708 15386 100       24842 $sigils .= '%' if $self->hash;
709 15386 100       25083 $sigils .= '&' if $self->code;
710 15386 100       27022 $sigils .= '*' if $self->egv;
711 15386 100       27357 $sigils .= 'I' if $self->io;
712 15386 50       26293 $sigils .= 'F' if $self->form;
713              
714 15386         38219 return "GLOB($sigils)";
715             }
716              
717             sub _outrefs
718             {
719 20422     20422   30593 my $self = shift;
720 20422         38270 my ( $match, $no_desc ) = @_;
721              
722 20422         29181 my @outrefs;
723              
724 20422 50       43558 if( $match & STRENGTH_STRONG ) {
725 20422         36744 foreach my $slot (qw( scalar array hash code io form )) {
726 122532 100       296913 my $sv = $self->$slot or next;
727 19422 100       69761 push @outrefs, $no_desc ? ( strong => $sv ) :
728             Devel::MAT::SV::Reference( "the $slot", strong => $sv );
729             }
730             }
731              
732 20422 100       47359 if( my $egv = $self->egv ) {
733             # the egv is weakref if if it points back to itself
734 20414         46134 my $egv_is_self = $egv == $self;
735              
736 20414 100       57554 if( $match & ( $egv_is_self ? STRENGTH_WEAK : STRENGTH_STRONG ) ) {
    50          
737 20414 100       39572 my $strength = $egv_is_self ? "weak" : "strong";
738 20414 100       51042 push @outrefs, $no_desc ? ( $strength => $egv ) :
739             Devel::MAT::SV::Reference( "the egv", $strength => $egv );
740             }
741             }
742              
743 20422         50044 foreach my $saved ( @{ $self->{saved} } ) {
  20422         65987  
744 4         16 my $sv = $self->df->sv_at( $saved->[1] );
745              
746 4 50       31 push @outrefs, $no_desc ? ( inferred => $sv ) :
747             Devel::MAT::SV::Reference( "saved value of " . Devel::MAT::Cmd->format_note( $saved->[0] ) . " slot",
748             "inferred", $sv );
749             }
750              
751 20422         51982 return @outrefs;
752             }
753              
754             sub _more_saved
755             {
756 5     5   12 my $self = shift;
757 5         12 my ( $slot, $addr ) = @_;
758              
759 5         10 push @{ $self->{saved} }, [ $slot => $addr ];
  5         26  
760             }
761              
762             package Devel::MAT::SV::SCALAR 0.50;
763 9     9   74 use base qw( Devel::MAT::SV );
  9         24  
  9         1054  
764             __PACKAGE__->register_type( 2 );
765 9     9   67 use constant $CONSTANTS;
  9         33  
  9         971  
766 9     9   60 use constant basetype => "SV";
  9         18  
  9         7866  
767              
768             =head1 Devel::MAT::SV::SCALAR
769              
770             Represents a non-referential scalar value; an SV of any of the types up to and
771             including C (that is, C, C, C, C, C or
772             C). This includes all numbers, integers and floats, strings, and dualvars
773             containing multiple parts.
774              
775             =cut
776              
777             sub load
778             {
779 217575     217575   340891 my $self = shift;
780 217575         354889 my ( $header, $ptrs, $strs ) = @_;
781 217575         424167 my $df = $self->df;
782              
783 217575         860352 my ( $flags, $uv, $nvbytes, $pvlen ) =
784             unpack "C $df->{uint_fmt} A$df->{nv_len} $df->{uint_fmt}", $header;
785 217575         468496 my $nv = unpack "$df->{nv_fmt}", $nvbytes;
786              
787             # $strs->[0] will be swiped
788              
789 217575         557969 $self->_set_scalar_fields( $flags, $uv, $nv,
790             $strs->[0], $pvlen,
791             $ptrs->[0], # OURSTASH
792             );
793              
794             # $strs->[0] is now undef
795              
796 217575         307052 $flags &= ~0x1f;
797 217575 50       563087 $flags and die sprintf "Unrecognised SCALAR flags %02x\n", $flags;
798             }
799              
800             =head2 uv
801              
802             $uv = $sv->uv
803              
804             Returns the integer numeric portion as an unsigned value, if valid, or C.
805              
806             =head2 iv
807              
808             $iv = $sv->iv
809              
810             Returns the integer numeric portion as a signed value, if valid, or C.
811              
812             =head2 nv
813              
814             $nv = $sv->nv
815              
816             Returns the floating numeric portion, if valid, or C.
817              
818             =head2 pv
819              
820             $pv = $sv->pv
821              
822             Returns the string portion, if valid, or C.
823              
824             =head2 pvlen
825              
826             $pvlen = $sv->pvlen
827              
828             Returns the length of the string portion, if valid, or C.
829              
830             =cut
831              
832             # XS accessors
833              
834             =head2 qq_pv
835              
836             $str = $sv->qq_pv( $maxlen )
837              
838             Returns the PV string, if defined, suitably quoted. If C<$maxlen> is defined
839             and the PV is longer than this, it is truncated and C<...> is appended after
840             the containing quote marks.
841              
842             =cut
843              
844             sub qq_pv
845             {
846 5     5   19 my $self = shift;
847 5         7 my ( $maxlen ) = @_;
848              
849 5 50       21 defined( my $pv = $self->pv ) or return undef;
850 5 100 66     22 $pv = substr( $pv, 0, $maxlen ) if defined $maxlen and $maxlen < length $pv;
851              
852 5         13 my $truncated = $self->pvlen > length $pv;
853              
854 5 100       20 if( $pv =~ m/^[\x20-\x7e]*$/ ) {
855 3         29 $pv =~ s/(['\\])/\\$1/g;
856 3         9 $pv = qq('$pv');
857             }
858             else {
859 2 50       17 $pv =~ s{(\") | (\r) | (\n) | ([\x00-\x1f\x80-\xff])}
  2 50       26  
    50          
860 2         6 {$1?'\\"' : $2?"\\r" : $3?"\\n" : sprintf "\\x%02x", ord $4}egx;
861             $pv = qq("$pv");
862 5 100       11 }
863             $pv .= "..." if $truncated;
864 5         23  
865             return $pv;
866             }
867              
868             =head2 ourstash
869              
870             $stash = $sv->ourstash
871              
872             Returns the stash of the SCALAR, if it is an 'C' variable.
873              
874             After perl 5.20 this is no longer used, and will return C.
875              
876             =cut
877 107811     107811   138431  
  107811         507853  
878             sub ourstash { my $self = shift; return $self->df->sv_at( $self->ourstash_at ) }
879              
880             sub symname
881 2     2   7 {
882 2 100       34 my $self = shift;
883 1         8 return unless my $glob_at = $self->glob_at;
884             return $mksymname->( '$', $self->df->sv_at( $glob_at ) );
885             }
886              
887             sub type
888 463693     463693   632076 {
889 463693 100 100     3318201 my $self = shift;
      100        
      100        
890 205543         608325 return "SCALAR" if defined $self->uv or defined $self->iv or defined $self->nv or defined $self->pv;
891             return "UNDEF";
892             }
893              
894             sub desc
895 107714     107714   494935 {
896             my $self = shift;
897 107714         124542  
898 107714 100       299144 my @flags;
899 107714 100       207671 push @flags, "UV" if defined $self->uv;
900 107714 100       204548 push @flags, "IV" if defined $self->iv;
901 107714 100       249772 push @flags, "NV" if defined $self->nv;
902 107714         151743 push @flags, "PV" if defined $self->pv;
903 107714 100       204121 local $" = ",";
904 62092         171688 return "UNDEF()" unless @flags;
905             return "SCALAR(@flags)";
906             }
907              
908             sub _outrefs
909 107811     107811   134383 {
910 107811         156484 my $self = shift;
911             my ( $match, $no_desc ) = @_;
912 107811         128805  
913             my @outrefs;
914 107811 50 33     232614  
915 0 0       0 if( $match & STRENGTH_STRONG and my $ourstash = $self->ourstash ) {
916             push @outrefs, $no_desc ? ( strong => $ourstash ) :
917             Devel::MAT::SV::Reference( "the our stash", strong => $ourstash );
918             }
919 107811         186218  
920             return @outrefs;
921             }
922              
923 9     9   68 package Devel::MAT::SV::REF 0.50;
  9         19  
  9         937  
924             use base qw( Devel::MAT::SV );
925 9     9   63 __PACKAGE__->register_type( 3 );
  9         16  
  9         812  
926 9     9   57 use constant $CONSTANTS;
  9         17  
  9         4301  
927             use constant basetype => "SV";
928              
929             =head1 Devel::MAT::SV::REF
930              
931             Represents a referential scalar; any SCALAR-type SV with the C flag
932             set.
933              
934             =cut
935              
936             sub load
937 26241     26241   41949 {
938 26241         45794 my $self = shift;
939             my ( $header, $ptrs, $strs ) = @_;
940 26241         47761  
941             ( my $flags ) =
942             unpack "C", $header;
943              
944 26241         39264 $self->_set_ref_fields(
  26241         84815  
945             @{$ptrs}[0,1], # RV, OURSTASH
946             $flags & 0x01, # RV_IS_WEAK
947             );
948 26241         42787  
949 26241 50       63359 $flags &= ~0x01;
950             $flags and die sprintf "Unrecognised REF flags %02x\n", $flags;
951             }
952              
953             =head2 rv
954              
955             $svrv = $sv->rv
956              
957             Returns the SV referred to by the reference.
958              
959             =cut
960 19071     19071   26764  
  19071         63563  
961             sub rv { my $self = shift; return $self->df->sv_at( $self->rv_at ) }
962              
963             =head2 is_weak
964              
965             $weak = $sv->is_weak
966              
967             Returns true if the SV is a weakened RV reference.
968              
969             =cut
970              
971             # XS accessor
972              
973             =head2 ourstash
974              
975             $stash = $sv->ourstash
976              
977             Returns the stash of the SCALAR, if it is an 'C' variable.
978              
979             =cut
980 7526     7526   10755  
  7526         21539  
981             sub ourstash { my $self = shift; return $self->df->sv_at( $self->ourstash_at ) }
982              
983             sub desc
984 7496     7496   36310 {
985             my $self = shift;
986 7496 100       34224  
987             return sprintf "REF(%s)", $self->is_weak ? "W" : "";
988             }
989              
990             *symname = \&Devel::MAT::SV::SCALAR::symname;
991              
992             sub _outrefs
993 7526     7526   9658 {
994 7526         10774 my $self = shift;
995             my ( $match, $no_desc ) = @_;
996 7526         9059  
997             my @outrefs;
998 7526         23218  
999 7526 100 33     22666 my $is_weak = $self->is_weak;
    50          
1000 7526 100       13991 if( $match & ( $is_weak ? STRENGTH_WEAK : STRENGTH_STRONG ) and my $rv = $self->rv ) {
1001 7526 100       16277 my $strength = $is_weak ? "weak" : "strong";
1002             push @outrefs, $no_desc ? ( $strength => $rv ) :
1003             Devel::MAT::SV::Reference( "the referrant", $strength => $rv );
1004             }
1005 7526 50 33     20139  
1006 0 0       0 if( $match & STRENGTH_STRONG and my $ourstash = $self->ourstash ) {
1007             push @outrefs, $no_desc ? ( strong => $ourstash ) :
1008             Devel::MAT::SV::Reference( "the our stash", strong => $ourstash );
1009             }
1010 7526         18068  
1011             return @outrefs;
1012             }
1013              
1014 9     9   64 package Devel::MAT::SV::BOOL 0.50;
  9         18  
  9         3592  
1015             use base qw( Devel::MAT::SV::SCALAR );
1016 0     0   0  
1017             sub type { return "BOOL" }
1018              
1019             sub desc
1020 0     0   0 {
1021 0 0       0 my $self = shift;
1022 0         0 return "BOOL(YES)" if $self->uv;
1023             return "BOOL(NO)";
1024             }
1025              
1026 9     9   65 package Devel::MAT::SV::ARRAY 0.50;
  9         22  
  9         1153  
1027             use base qw( Devel::MAT::SV );
1028 9     9   68 __PACKAGE__->register_type( 4 );
  9         37  
  9         934  
1029 9     9   71 use constant $CONSTANTS;
  9         16  
  9         8567  
1030             use constant basetype => "AV";
1031              
1032             =head1 Devel::MAT::SV::ARRAY
1033              
1034             Represents an array; an SV of type C.
1035              
1036             =cut
1037              
1038             sub refcount_adjusted
1039 0     0   0 {
1040             my $self = shift;
1041 0 0       0 # AVs that are backrefs lists have an SvREFCNT artificially high
1042             return $self->refcnt - ( $self->is_backrefs ? 1 : 0 );
1043             }
1044              
1045             sub load
1046 56927     56927   86499 {
1047 56927         97673 my $self = shift;
1048 56927         116142 my ( $header, $ptrs, $strs ) = @_;
1049             my $df = $self->df;
1050 56927         156977  
1051             my ( $n, $flags ) =
1052             unpack "$df->{uint_fmt} C", $header;
1053 56927 100 100     240494  
1054             $self->_set_array_fields( $flags || 0, [ $n ? $df->_read_ptrs($n) : () ] );
1055             }
1056              
1057             sub _more_saved
1058 1     1   3 {
1059 1         4 my $self = shift;
1060             my ( $index, $addr ) = @_;
1061 1         2  
  1         6  
1062             push @{ $self->{saved} }, [ $index => $addr ];
1063             }
1064              
1065             =head2 is_unreal
1066              
1067             $unreal = $av->is_unreal
1068              
1069             Returns true if the C flag is not set on the array - i.e. that its
1070             SV pointers do not contribute to the C of the SVs it points at.
1071              
1072             =head2 is_backrefs
1073              
1074             $backrefs = $av->is_backrefs
1075              
1076             Returns true if the array contains the backrefs list of a hash or
1077             weakly-referenced object.
1078              
1079             =cut
1080              
1081             # XS accessors
1082              
1083             sub symname
1084 4     4   13 {
1085 4 100       46 my $self = shift;
1086 1         8 return unless my $glob_at = $self->glob_at;
1087             return $mksymname->( '@', $self->df->sv_at( $glob_at ) );
1088             }
1089              
1090             =head2 elems
1091              
1092             @svs = $av->elems
1093              
1094             Returns all of the element SVs in a list
1095              
1096             =cut
1097              
1098             sub elems
1099 22240     22240   41799 {
1100             my $self = shift;
1101 22240         55145  
1102 22240 100       64699 my $n = $self->n_elems;
1103             return $n unless wantarray;
1104 12876         28569  
1105 12876         145972 my $df = $self->df;
  5410448         10973360  
1106             return map { $df->sv_at( $self->elem_at( $_ ) ) } 0 .. $n-1;
1107             }
1108              
1109             =head2 elem
1110              
1111             $sv = $av->elem( $index )
1112              
1113             Returns the SV at the given index
1114              
1115             =cut
1116              
1117             sub elem
1118 4426717     4426717   5750822 {
1119 4426717         12345341 my $self = shift;
1120             return $self->df->sv_at( $self->elem_at( $_[0] ) );
1121             }
1122              
1123             sub desc
1124 9513     9513   46279 {
1125             my $self = shift;
1126 9513         26789  
1127             my @flags = $self->n_elems;
1128 9513 100       22280  
1129             push @flags, "!REAL" if $self->is_unreal;
1130 9513         13284  
1131 9513         27876 $" = ",";
1132             return "ARRAY(@flags)";
1133             }
1134              
1135             sub _outrefs
1136 12952     12952   21287 {
1137 12952         23351 my $self = shift;
1138             my ( $match, $no_desc ) = @_;
1139 12952         40661  
1140             my $n = $self->n_elems;
1141 12952         23948  
1142             my @outrefs;
1143 12952 100       38121  
1144 10533 50       23951 if( $self->is_unreal ) {
1145 10533         29101 if( $match & STRENGTH_WEAK ) {
1146 4374943 50       26647280 foreach my $idx ( 0 .. $n-1 ) {
1147             my $sv = $self->elem( $idx ) or next;
1148 4374943 100       10814147  
1149             push @outrefs, $no_desc ? ( weak => $sv ) :
1150             Devel::MAT::SV::Reference( "element " . Devel::MAT::Cmd->format_value( $idx, index => 1 ), weak => $sv );
1151             }
1152             }
1153             }
1154 2419         5745 else {
1155 25094 100       44565 foreach my $idx ( 0 .. $n-1 ) {
1156             my $sv = $self->elem( $idx ) or next;
1157 25002 100       51113  
1158             my $name = $no_desc ? undef :
1159 25002 100       46807 "element " . Devel::MAT::Cmd->format_value( $idx, index => 1 );
1160 25001 100       50135 if( $match & STRENGTH_STRONG ) {
1161             push @outrefs, $no_desc ? ( strong => $sv ) :
1162             Devel::MAT::SV::Reference( $name, strong => $sv );
1163 25002 50 100     126003 }
      66        
      66        
1164 2989 100       8332 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1165             push @outrefs, $no_desc ? ( indirect => $rv ) :
1166             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1167             }
1168             }
1169             }
1170 12952         43523  
  12952         50594  
1171 1         6 foreach my $saved ( @{ $self->{saved} } ) {
1172             my $sv = $self->df->sv_at( $saved->[1] );
1173 1 50       6  
1174             push @outrefs, $no_desc ? ( inferred => $sv ) :
1175             Devel::MAT::SV::Reference( "saved value of element " . Devel::MAT::Cmd->format_value( $saved->[0], index => 1 ),
1176             inferred => $sv );
1177             }
1178 12952         541348  
1179             return @outrefs;
1180             }
1181              
1182             package Devel::MAT::SV::PADLIST 0.50;
1183 9     9   70 # Synthetic type
  9         21  
  9         2839  
1184 9     9   70 use base qw( Devel::MAT::SV::ARRAY );
  9         18  
  9         461  
1185 9     9   57 use constant type => "PADLIST";
  9         25  
  9         3508  
1186             use constant $CONSTANTS;
1187              
1188             =head1 Devel::MAT::SV::PADLIST
1189              
1190             A subclass of ARRAY, this is used to represent the PADLIST of a CODE SV.
1191              
1192             =cut
1193 0     0   0  
  0         0  
1194             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1195              
1196             sub desc
1197 0     0   0 {
1198 0         0 my $self = shift;
1199             return "PADLIST(" . $self->n_elems . ")";
1200             }
1201              
1202             # Totally different outrefs format than ARRAY
1203             sub _outrefs
1204 0     0   0 {
1205 0         0 my $self = shift;
1206             my ( $match, $no_desc ) = @_;
1207 0         0  
1208             my @outrefs;
1209 0 0       0  
1210 0         0 if( $match & STRENGTH_STRONG ) {
1211 0         0 my $df = $self->df;
1212             my $n = $self->n_elems;
1213 0 0       0  
1214 0 0       0 if( my $padnames = $df->sv_at( $self->elem_at( 0 ) ) ) {
1215             push @outrefs, $no_desc ? ( strong => $padnames ) :
1216             Devel::MAT::SV::Reference( "the padnames", strong => $padnames );
1217             }
1218 0         0  
1219 0 0       0 foreach my $idx ( 1 .. $n-1 ) {
1220             my $pad = $df->sv_at( $self->elem_at( $idx ) ) or next;
1221 0 0       0  
1222             push @outrefs, $no_desc ? ( strong => $pad ) :
1223             Devel::MAT::SV::Reference( "pad at depth $idx", strong => $pad );
1224             }
1225             }
1226 0         0  
1227             return @outrefs;
1228             }
1229              
1230             package Devel::MAT::SV::PADNAMES 0.50;
1231 9     9   65 # Synthetic type
  9         18  
  9         2466  
1232 9     9   75 use base qw( Devel::MAT::SV::ARRAY );
  9         17  
  9         435  
1233 9     9   47 use constant type => "PADNAMES";
  9         20  
  9         4616  
1234             use constant $CONSTANTS;
1235              
1236             =head1 Devel::MAT::SV::PADNAMES
1237              
1238             A subclass of ARRAY, this is used to represent the PADNAMES of a CODE SV.
1239              
1240             =cut
1241 0     0   0  
  0         0  
1242             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1243              
1244             =head2 padname
1245              
1246             $padname = $padnames->padname( $padix )
1247              
1248             Returns the name of the lexical at the given index, or C
1249              
1250             =cut
1251              
1252             sub padname
1253 0     0   0 {
1254 0         0 my $self = shift;
1255 0 0       0 my ( $padix ) = @_;
1256 0 0       0 my $namepv = $self->elem( $padix ) or return undef;
1257 0         0 $namepv->type eq "SCALAR" or return undef;
1258             return $namepv->pv;
1259             }
1260              
1261             =head2 padix_from_padname
1262              
1263             $padix = $padnames->padix_from_padname( $padname )
1264              
1265             Returns the index of the lexical with the given name, or C
1266              
1267             =cut
1268              
1269             sub padix_from_padname
1270 0     0   0 {
1271 0         0 my $self = shift;
1272             my ( $padname ) = @_;
1273 0         0  
1274 0         0 foreach my $padix ( 1 .. scalar( $self->elems ) - 1 ) {
1275 0 0 0     0 my $namepv;
      0        
1276             return $padix if $namepv = $self->elem( $padix ) and
1277             $namepv->type eq "SCALAR" and
1278             $namepv->pv eq $padname;
1279             }
1280 0         0  
1281             return undef;
1282             }
1283              
1284             sub desc
1285 0     0   0 {
1286 0         0 my $self = shift;
1287             return "PADNAMES(" . scalar($self->elems) . ")";
1288             }
1289              
1290             # Totally different outrefs format than ARRAY
1291             sub _outrefs
1292 0     0   0 {
1293 0         0 my $self = shift;
1294             my ( $match, $no_desc ) = @_;
1295 0         0  
1296             my @outrefs;
1297 0 0       0  
1298 0         0 if( $match & STRENGTH_STRONG ) {
1299 0         0 my $df = $self->df;
1300             my $n = $self->n_elems;
1301 0         0  
1302 0 0       0 foreach my $idx ( 1 .. $n-1 ) {
1303             my $padname = $df->sv_at( $self->elem_at( $idx ) ) or next;
1304 0 0       0  
1305             push @outrefs, $no_desc ? ( strong => $padname ) :
1306             Devel::MAT::SV::Reference( "padname " . Devel::MAT::Cmd->format_value( $idx, index => 1 ), strong => $padname );
1307             }
1308             }
1309 0         0  
1310             return @outrefs;
1311             }
1312              
1313             package Devel::MAT::SV::PAD 0.50;
1314 9     9   66 # Synthetic type
  9         21  
  9         2530  
1315 9     9   66 use base qw( Devel::MAT::SV::ARRAY );
  9         22  
  9         453  
1316 9     9   55 use constant type => "PAD";
  9         18  
  9         6439  
1317             use constant $CONSTANTS;
1318              
1319             =head1 Devel::MAT::SV::PAD
1320              
1321             A subclass of ARRAY, this is used to represent a PAD of a CODE SV.
1322              
1323             =cut
1324              
1325             sub desc
1326 6749     6749   35006 {
1327 6749         12274 my $self = shift;
1328             return "PAD(" . scalar($self->elems) . ")";
1329             }
1330              
1331             =head2 padcv
1332              
1333             $cv = $pad->padcv
1334              
1335             Returns the C SV for which this is a pad.
1336              
1337             =cut
1338 6779     6779   9684  
  6779         34086  
1339             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1340              
1341             =head2 lexvars
1342              
1343             ( $name, $sv, $name, $sv, ... ) = $pad->lexvars
1344              
1345             Returns a name/value list of the lexical variables in the pad.
1346              
1347             =cut
1348              
1349             sub lexvars
1350 0     0   0 {
1351 0         0 my $self = shift;
1352             my $padcv = $self->padcv;
1353 0         0  
1354             my @svs = $self->elems;
1355 0         0 return map {
  0         0  
1356 0 0       0 my $padname = $padcv->padname( $_ );
1357             $padname ? ( $padname->name => $svs[$_] ) : ()
1358             } 1 .. $#svs;
1359             }
1360              
1361             =head2 maybe_lexvar
1362              
1363             $sv = $pad->maybe_lexvar( $padname )
1364              
1365             I
1366              
1367             Returns the SV associated with the given padname if one exists, or C if
1368             not.
1369              
1370             Used to be named C.
1371              
1372             =cut
1373              
1374             sub maybe_lexvar
1375 4     4   7 {
1376 4         11 my $self = shift;
1377             my ( $padname ) = @_;
1378 4 50       10  
1379 4         64 my $padix = $self->padcv->padix_from_padname( $padname ) or return undef;
1380             return $self->elem( $padix );
1381             }
1382              
1383             *lexvar = \&maybe_lexvar;
1384              
1385             # Totally different outrefs format than ARRAY
1386             sub _outrefs
1387 6773     6773   9517 {
1388 6773         10271 my $self = shift;
1389             my ( $match, $no_desc ) = @_;
1390 6773         13164  
1391             my $padcv = $self->padcv;
1392 6773         14109  
1393             my @svs = $self->elems;
1394 6773         11736  
1395             my @outrefs;
1396 6773 100 66     25334  
1397 6270 100       14491 if( $match & STRENGTH_STRONG and my $argsav = $svs[0] ) {
1398             push @outrefs, $no_desc ? ( strong => $argsav ) :
1399             Devel::MAT::SV::Reference( "the " . Devel::MAT::Cmd->format_note( '@_', 1 ) . " av", strong => $argsav );
1400             }
1401 6773         15108  
1402 51819 100       101225 foreach my $idx ( 1 .. $#svs ) {
1403             my $sv = $svs[$idx] or next;
1404 48973         56393  
1405 48973 100       73001 my $name;
1406 242         430 if( !$no_desc ) {
1407 242 100       579 my $padname = $padcv->padname( $idx );
1408 242 100       1018 $name = $padname ? $padname->name : undef;
1409 70         164 if( $name ) {
1410             $name = "the lexical " . Devel::MAT::Cmd->format_note( $name, 1 );
1411             }
1412 172         304 else {
1413             $name = "pad temporary $idx";
1414             }
1415             }
1416 48973 50       80041  
1417 48973 100       81531 if( $match & STRENGTH_STRONG ) {
1418             push @outrefs, $no_desc ? ( strong => $sv ) :
1419             Devel::MAT::SV::Reference( $name, strong => $sv );
1420 48973 50 66     103642 }
      66        
      66        
1421 423 100       1618 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1422             push @outrefs, $no_desc ? ( indirect => $rv ) :
1423             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1424             }
1425             }
1426 6773         29847  
1427             return @outrefs;
1428             }
1429              
1430 9     9   84 package Devel::MAT::SV::HASH 0.50;
  9         64  
  9         938  
1431             use base qw( Devel::MAT::SV );
1432 9     9   62 __PACKAGE__->register_type( 5 );
  9         28  
  9         808  
1433 9     9   69 use constant $CONSTANTS;
  9         16  
  9         9540  
1434             use constant basetype => "HV";
1435              
1436             =head1 Devel::MAT::SV::HASH
1437              
1438             Represents a hash; an SV of type C. The C
1439             subclass is used to represent hashes that are used as stashes.
1440              
1441             =cut
1442              
1443             sub load
1444 10025     10025   17638 {
1445 10025         18381 my $self = shift;
1446 10025         21589 my ( $header, $ptrs, $strs ) = @_;
1447             my $df = $self->df;
1448 10025         29445  
1449             ( my $n ) =
1450             unpack "$df->{uint_fmt} a*", $header;
1451 10025         17977  
1452 10025         27757 my %values_at;
1453 169721         319694 foreach ( 1 .. $n ) {
1454 169721         324605 my $key = $df->_read_str;
1455             $values_at{$key} = $df->_read_ptr;
1456             }
1457              
1458 10025         233282 $self->_set_hash_fields(
1459             $ptrs->[0], # BACKREFS
1460             \%values_at,
1461             );
1462              
1463             }
1464              
1465             # Back-compat. for loading old .pmat files that didn't store AvREAL
1466             sub _fixup
1467 10025     10025   14441 {
1468             my $self = shift;
1469 10025 100       17464  
1470 2264 100       9780 if( my $backrefs = $self->backrefs ) {
1471             $backrefs->_set_backrefs( 1 ) if $backrefs->type eq "ARRAY";
1472             }
1473             }
1474              
1475             sub _more_saved
1476 1     1   5 {
1477 1         5 my $self = shift;
1478             my ( $keyaddr, $valaddr ) = @_;
1479 1         2  
  1         7  
1480             push @{ $self->{saved} }, [ $keyaddr, $valaddr ];
1481             }
1482              
1483             sub symname
1484 3     3   10 {
1485 3 50       31 my $self = shift;
1486 3         21 return unless my $glob_at = $self->glob_at;
1487             return $mksymname->( '%', $self->df->sv_at( $glob_at ) );
1488             }
1489              
1490             # HVs have a backrefs field directly, rather than using magic
1491             sub backrefs
1492 23994     23994   41544 {
1493 23994         93751 my $self = shift;
1494             return $self->df->sv_at( $self->backrefs_at );
1495             }
1496              
1497             =head2 keys
1498              
1499             @keys = $hv->keys
1500              
1501             Returns the set of keys present in the hash, as plain perl strings, in no
1502             particular order.
1503              
1504             =cut
1505              
1506             # XS accessor
1507              
1508             =head2 value
1509              
1510             $sv = $hv->value( $key )
1511              
1512             Returns the SV associated with the given key
1513              
1514             =cut
1515              
1516             sub value
1517 7863     7863   11971 {
1518 7863         12183 my $self = shift;
1519 7863         26785 my ( $key ) = @_;
1520             return $self->df->sv_at( $self->value_at( $key ) );
1521             }
1522              
1523             =head2 values
1524              
1525             @svs = $hv->values
1526              
1527             Returns all of the SVs stored as values, in no particular order (though, in an
1528             order corresponding to the order returned by C).
1529              
1530             =cut
1531              
1532             sub values
1533 536     536   723 {
1534 536 50       930 my $self = shift;
1535             return $self->n_values if !wantarray;
1536 536         1388  
1537 536         1509 my $df = $self->df;
  3904         6520  
1538             return map { $df->sv_at( $_ ) } $self->values_at;
1539             }
1540              
1541             sub desc
1542 2864     2864   12111 {
1543 2864 100       10528 my $self = shift;
1544 2864         9098 my $named = $self->{name} ? " named $self->{name}" : "";
1545             return "HASH(" . $self->n_values . ")";
1546             }
1547              
1548             sub _outrefs
1549 7961     7961   19640 {
1550 7961         18698 my $self = shift;
1551             my ( $match, $no_desc ) = @_;
1552 7961         28996  
1553             my $df = $self->df;
1554 7961         13504  
1555             my @outrefs;
1556 7961 100       26473  
1557             if( my $backrefs = $self->backrefs ) {
1558             # backrefs are optimised so if there's only one backref, it is stored
1559 5684 100       28102 # in the backrefs slot directly
1560 5674 50       19415 if( $backrefs->type eq "ARRAY" ) {
1561 5674 100       25399 if( $match & STRENGTH_STRONG ) {
1562             push @outrefs, $no_desc ? ( strong => $backrefs ) :
1563             Devel::MAT::SV::Reference( "the backrefs list", strong => $backrefs );
1564             }
1565 5674 50       43890  
1566 5674         13865 if( $match & STRENGTH_INDIRECT ) {
1567 5348128 100       27353993 foreach my $sv ( $self->backrefs->elems ) {
1568             push @outrefs, $no_desc ? ( indirect => $sv ) :
1569             Devel::MAT::SV::Reference( "a backref", indirect => $sv );
1570             }
1571             }
1572             }
1573 10 50       50 else {
1574 10 50       49 if( $match & STRENGTH_WEAK ) {
1575             push @outrefs, $no_desc ? ( weak => $backrefs ) :
1576             Devel::MAT::SV::Reference( "a backref", weak => $backrefs );
1577             }
1578             }
1579             }
1580 7961         953789  
1581 2293147 100       9710193 foreach my $key ( $self->keys ) {
1582 2269069 100       5367812 my $sv = $df->sv_at( $self->value_at( $key ) ) or next;
1583             my $name = $no_desc ? undef :
1584             "value " . Devel::MAT::Cmd->format_value( $key, key => 1 );
1585 2269069 50       4563776  
1586 2269069 100       4938988 if( $match & STRENGTH_STRONG ) {
1587             push @outrefs, $no_desc ? ( strong => $sv ) :
1588             Devel::MAT::SV::Reference( $name, strong => $sv );
1589 2269069 50 66     17409162 }
      66        
      66        
1590 4679 100       12975 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1591             push @outrefs, $no_desc ? ( indirect => $sv ) :
1592             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1593             }
1594             }
1595 7961         244026  
  7961         39345  
1596 1         5 foreach my $saved ( @{ $self->{saved} } ) {
1597 1         5 my $keysv = $self->df->sv_at( $saved->[0] );
1598             my $valsv = $self->df->sv_at( $saved->[1] );
1599 1 50       5  
1600             push @outrefs, $no_desc ? ( inferred => $keysv ) :
1601             Devel::MAT::SV::Reference( "a key for saved value",
1602 1 50       40 inferred => $keysv );
1603             push @outrefs, $no_desc ? ( inferred => $valsv ) :
1604             Devel::MAT::SV::Reference( "saved value of value " . Devel::MAT::Cmd->format_value( $keysv->pv, key => 1 ),
1605             inferred => $valsv );
1606             }
1607 7961         691069  
1608             return @outrefs;
1609             }
1610              
1611 9     9   70 package Devel::MAT::SV::STASH 0.50;
  9         14  
  9         2947  
1612             use base qw( Devel::MAT::SV::HASH );
1613 9     9   69 __PACKAGE__->register_type( 6 );
  9         19  
  9         7309  
1614             use constant $CONSTANTS;
1615              
1616             =head1 Devel::MAT::SV::STASH
1617              
1618             Represents a hash used as a stash; an SV of type C whose C
1619             is non-NULL. This is a subclass of C.
1620              
1621             =cut
1622              
1623             sub load
1624 2334     2334   4675 {
1625 2334         5851 my $self = shift;
1626 2334         6178 my ( $header, $ptrs, $strs ) = @_;
1627             my $df = $self->df;
1628 2334         3621  
  2334         6032  
1629             my ( $hash_bytes, $hash_ptrs, $hash_strs ) = @{ $df->{sv_sizes}[5] };
1630 2334         17174  
1631             $self->SUPER::load(
1632             substr( $header, 0, $hash_bytes, "" ),
1633             [ splice @$ptrs, 0, $hash_ptrs ],
1634             [ splice @$strs, 0, $hash_strs ],
1635             );
1636 2334         14499  
  2334         11189  
1637             @{$self}{qw( mro_linearall_at mro_linearcurrent_at mro_nextmethod_at mro_isa_at )} =
1638             @$ptrs;
1639 2334         10182  
1640             ( $self->{name} ) =
1641             @$strs;
1642             }
1643              
1644             =head2 mro_linear_all
1645              
1646             =head2 mro_linearcurrent
1647              
1648             =head2 mro_nextmethod
1649              
1650             =head2 mro_isa
1651              
1652             $hv = $stash->mro_linear_all
1653              
1654             $sv = $stash->mro_linearcurrent
1655              
1656             $sv = $stash->mro_nextmethod
1657              
1658             $av = $stash->mro_isa
1659              
1660             Returns the fields from the MRO structure
1661              
1662             =cut
1663 6037     6037   12430  
  6037         42850  
1664 6037     6037   11096 sub mro_linearall { my $self = shift; return $self->df->sv_at( $self->{mro_linearall_at} ) }
  6037         26917  
1665 6037     6037   12438 sub mro_linearcurrent { my $self = shift; return $self->df->sv_at( $self->{mro_linearcurrent_at} ) }
  6037         23408  
1666 6037     6037   11593 sub mro_nextmethod { my $self = shift; return $self->df->sv_at( $self->{mro_nextmethod_at} ) }
  6037         20557  
1667             sub mro_isa { my $self = shift; return $self->df->sv_at( $self->{mro_isa_at} ) }
1668              
1669             =head2 value_code
1670              
1671             $cv = $stash->value_code( $key )
1672              
1673             Returns the CODE associated with the given symbol name, if it exists, or
1674             C if not. This is roughly equivalent to
1675              
1676             $cv = $stash->value( $key )->code
1677              
1678             Except that it is aware of the direct reference to CVs that perl 5.22 will
1679             optimise for. This method should be used in preference to the above construct.
1680              
1681             =cut
1682              
1683             sub value_code
1684 1     1   304 {
1685 1         4 my $self = shift;
1686             my ( $key ) = @_;
1687 1 50       4  
1688 1 50       11 my $sv = $self->value( $key ) or return undef;
    0          
1689 1         6 if( $sv->type eq "GLOB" ) {
1690             return $sv->code;
1691             }
1692 0         0 elsif( $sv->type eq "REF" ) {
1693             return $sv->rv;
1694             }
1695 0         0  
  0         0  
1696             die "TODO: value_code on non-GLOB, non-REF ${\ $sv->desc }";
1697             }
1698              
1699             =head2 stashname
1700              
1701             $name = $stash->stashname
1702              
1703             Returns the name of the stash
1704              
1705             =cut
1706              
1707             sub stashname
1708 28     28   65 {
1709 28         267 my $self = shift;
1710             return $self->{name};
1711             }
1712              
1713             sub desc
1714 667     667   3431 {
1715 667         1471 my $self = shift;
1716 667         2741 my $desc = $self->SUPER::desc;
1717 667         1591 $desc =~ s/^HASH/STASH/;
1718             return $desc;
1719             }
1720              
1721             sub _outrefs
1722 5704     5704   15695 {
1723 5704         20155 my $self = shift;
1724             my ( $match, $no_desc ) = @_;
1725 5704         23470  
1726             my @outrefs = $self->SUPER::_outrefs( @_ );
1727 5704 50       52532  
1728 5704 50       28617 if( $match & STRENGTH_STRONG ) {
1729 0 0       0 if( my $sv = $self->mro_linearall ) {
1730             push @outrefs, $no_desc ? ( strong => $sv ) :
1731             Devel::MAT::SV::Reference( "the mro linear all HV", strong => $sv );
1732 5704 100       18168 }
1733 1958 100       8185 if( my $sv = $self->mro_linearcurrent ) {
1734             push @outrefs, $no_desc ? ( strong => $sv ) :
1735             Devel::MAT::SV::Reference( "the mro linear current", strong => $sv );
1736 5704 50       25659 }
1737 0 0       0 if( my $sv = $self->mro_nextmethod ) {
1738             push @outrefs, $no_desc ? ( strong => $sv ) :
1739             Devel::MAT::SV::Reference( "the mro next::method", strong => $sv );
1740 5704 100       22420 }
1741 1958 100       7608 if( my $sv = $self->mro_isa ) {
1742             push @outrefs, $no_desc ? ( strong => $sv ) :
1743             Devel::MAT::SV::Reference( "the mro ISA cache", strong => $sv );
1744             }
1745             }
1746 5704         430202  
1747             return @outrefs;
1748             }
1749              
1750 9     9   67 package Devel::MAT::SV::CODE 0.50;
  9         21  
  9         1088  
1751             use base qw( Devel::MAT::SV );
1752 9     9   64 __PACKAGE__->register_type( 7 );
  9         18  
  9         999  
1753 9     9   61 use constant $CONSTANTS;
  9         21  
  9         516  
1754             use constant basetype => "CV";
1755 9     9   72  
  9         20  
  9         661  
1756             use Carp;
1757 9     9   57  
  9         204  
  9         661  
1758             use List::Util 1.44 qw( uniq );
1759 9     9   59  
  9         137  
  9         56  
1760             use Struct::Dumb 0.07 qw( struct );
1761             struct Padname => [qw( name ourstash flags fieldix fieldstash_at )];
1762 9     9   775 {
  9         28  
  9         28149  
1763 0     0   0 no strict 'refs';
1764 0     0   0 *{__PACKAGE__."::Padname::is_outer"} = sub { shift->flags & 0x01 };
1765 0     0   0 *{__PACKAGE__."::Padname::is_state"} = sub { shift->flags & 0x02 };
1766 0     0   0 *{__PACKAGE__."::Padname::is_lvalue"} = sub { shift->flags & 0x04 };
1767 0     0   0 *{__PACKAGE__."::Padname::is_typed"} = sub { shift->flags & 0x08 };
1768             *{__PACKAGE__."::Padname::is_our"} = sub { shift->flags & 0x10 };
1769              
1770 0     0   0 # Internal flags, not appearing in the file itself
1771             *{__PACKAGE__."::Padname::is_field"} = sub { shift->flags & 0x100 };
1772             }
1773              
1774             =head1 Devel::MAT::SV::CODE
1775              
1776             Represents a function or closure; an SV of type C.
1777              
1778             =cut
1779              
1780             sub load
1781 43400     43400   69206 {
1782 43400         76923 my $self = shift;
1783 43400         93150 my ( $header, $ptrs, $strs ) = @_;
1784             my $df = $self->df;
1785 43400         151496  
1786             my ( $line, $flags, $oproot, $depth ) =
1787             unpack "$df->{uint_fmt} C $df->{ptr_fmt} $df->{u32_fmt}", $header;
1788 43400 50       94196  
1789             defined $depth or $depth = -1;
1790              
1791 43400         71781 $self->_set_code_fields( $line, $flags, $oproot, $depth,
1792 43400         69776 @{$ptrs}[0, 2..4], # STASH, OUTSIDE, PADLIST, CONSTVAL
  43400         170352  
1793             @{$strs}[0, 1], # FILE, NAME
1794 43400         122090 );
1795             $self->_set_glob_at( $ptrs->[1] );
1796              
1797 43400 50       140993 # After perl 5.20 individual padname structs are no longer arena-allocated
1798             $self->{padnames} = [] if $df->{perlver} > ( ( 5 << 24 ) | ( 20 << 16 ) | 0xffff );
1799 43400         104876  
1800             while( my $type = $df->_read_u8 ) {
1801 117242         139670 match( $type : == ) {
  117242         246468  
1802 0         0 case( 1 ) { push @{ $self->{consts_at} }, $df->_read_ptr }
  0         0  
1803 43516         55064 case( 2 ) { push @{ $self->{constix} }, $df->_read_uint }
  43516         103050  
1804 0         0 case( 3 ) { push @{ $self->{gvs_at} }, $df->_read_ptr }
  0         0  
1805 172852         316418 case( 4 ) { push @{ $self->{gvix} }, $df->_read_uint }
1806 172852         273507 case( 5 ) { my $padix = $df->_read_uint;
1807             $self->{padnames}[$padix] = _load_padname( $df ); }
1808 0         0 case( 6 ) { # ignore - used to be padsvs_at
  0         0  
  0         0  
1809 23569         47293 $df->_read_uint; $df->_read_uint; $df->_read_ptr; }
1810 23639         47308 case( 7 ) { $self->_set_padnames_at( $df->_read_ptr ); }
1811 23639         48645 case( 8 ) { my $depth = $df->_read_uint;
1812 34102         73909 $self->{pads_at}[$depth] = $df->_read_ptr; }
1813 34102         66712 case( 9 ) { my $padname = $self->{padnames}[ $df->_read_uint ];
1814 0         0 $padname->flags = $df->_read_u8; }
1815 0         0 case( 10 ) { my $padname = $self->{padnames}[ $df->_read_uint ];
1816 0         0 $padname->flags |= 0x100;
1817 0         0 $padname->fieldix = $df->_read_uint;
1818 414920 100       1032869 $padname->fieldstash_at = $df->_read_ptr; }
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    0          
1819 0         0 default {
1820             die "TODO: unhandled CODEx type $type";
1821             }
1822             }
1823             }
1824             }
1825              
1826             sub _load_padname
1827 172852     172852   251079 {
1828             my ( $df ) = @_;
1829 172852         312838  
1830             return Padname( $df->_read_str, $df->_read_ptr, 0, 0, 0 );
1831             }
1832              
1833             sub _fixup
1834 43400     43400   58785 {
1835             my $self = shift;
1836 43400         107153  
1837             my $df = $self->df;
1838 43400         68949  
1839 43400 50       75923 my $padlist = $self->padlist;
1840 0         0 if( $padlist ) {
1841 0         0 bless $padlist, "Devel::MAT::SV::PADLIST";
1842             $padlist->_set_padcv_at( $self->addr );
1843             }
1844 43400         56354  
1845             my $padnames;
1846             my @pads;
1847              
1848 43400 50       74401 # 5.18.0 onwards has a totally different padlist arrangement
    0          
1849 43400         69688 if( $df->{perlver} >= ( ( 5 << 24 ) | ( 18 << 16 ) ) ) {
1850             $padnames = $self->padnames_av;
1851 43400         59082  
  47208         82141  
  43400         152033  
1852 43400         65532 @pads = map { $df->sv_at( $_ ) } @{ $self->{pads_at} };
1853             shift @pads; # always zero
1854             }
1855             elsif( $padlist ) {
1856             # PADLIST[0] stores the names of the lexicals
1857 0         0 # The rest stores the actual pads
1858 0         0 ( $padnames, @pads ) = $padlist->elems;
1859             $self->_set_padnames_at( $padnames->addr );
1860             }
1861 43400 50       72556  
1862 0         0 if( $padnames ) {
1863 0         0 bless $padnames, "Devel::MAT::SV::PADNAMES";
1864             $padnames->_set_padcv_at( $self->addr );
1865 0         0  
1866             $self->{padnames} = \my @padnames;
1867 0         0  
1868 0 0       0 foreach my $padix ( 1 .. $padnames->elems - 1 ) {
1869 0 0       0 my $padnamesv = $padnames->elem( $padix ) or next;
1870             $padnamesv->immortal and next; # UNDEF
1871 0         0  
1872             $padnames[$padix] = Padname( $padnamesv->pv, $padnamesv->ourstash, 0, 0, 0 );
1873             }
1874             }
1875 43400         65714  
1876 23639 100       43792 foreach my $pad ( @pads ) {
1877             next unless $pad;
1878 23632         35776  
1879 23632         69790 bless $pad, "Devel::MAT::SV::PAD";
1880             $pad->_set_padcv_at( $self->addr );
1881             }
1882 43400         80754  
1883             $self->{pads} = \@pads;
1884              
1885 43400 50       85003 # Under ithreads, constants and captured GVs are actually stored in the first padlist
1886 0         0 if( $df->ithreads ) {
1887             my $pad0 = $pads[0];
1888 0         0  
1889 0 0       0 foreach my $type (qw( const gv )) {
1890 0   0     0 my $idxes = $self->{"${type}ix"} or next;
1891             my $svs_at = $self->{"${type}s_at"} ||= [];
1892 0         0  
  0         0  
1893 0 0       0 @$svs_at = map { my $e = $pad0->elem($_);
1894             $e ? $e->addr : undef } uniq @$idxes;
1895             }
1896             }
1897 43400 100 66     146218  
1898 3286 50       11055 if( $self->is_cloned and my $oproot = $self->oproot ) {
1899 3286         10973 if( my $protosub = $df->{protosubs_by_oproot}{$oproot} ) {
1900             $self->_set_protosub_at( $protosub->addr );
1901             }
1902             }
1903             }
1904              
1905             =head2 stash
1906              
1907             =head2 glob
1908              
1909             =head2 file
1910              
1911             =head2 line
1912              
1913             =head2 scope
1914              
1915             =head2 padlist
1916              
1917             =head2 constval
1918              
1919             =head2 oproot
1920              
1921             =head2 depth
1922              
1923             $stash = $cv->stash
1924              
1925             $gv = $cv->glob
1926              
1927             $filename = $cv->file
1928              
1929             $line = $cv->line
1930              
1931             $scope_cv = $cv->scope
1932              
1933             $av = $cv->padlist
1934              
1935             $sv = $cv->constval
1936              
1937             $addr = $cv->oproot
1938              
1939             $depth = $cv->depth
1940              
1941             Returns the stash, glob, filename, line number, scope, padlist, constant value,
1942             oproot or depth of the code.
1943              
1944             =cut
1945 15791     15791   24186  
  15791         49665  
1946 15814     15814   23319 sub stash { my $self = shift; return $self->df->sv_at( $self->stash_at ) }
  15814         47714  
1947             sub glob { my $self = shift; return $self->df->sv_at( $self->glob_at ) }
1948 21216     21216   31120 # XS accessors: file, line
  21216         62496  
1949 64616     64616   85077 sub scope { my $self = shift; return $self->df->sv_at( $self->outside_at ) }
  64616         216903  
1950 33615     33615   46720 sub padlist { my $self = shift; return $self->df->sv_at( $self->padlist_at ) }
  33615         108014  
1951             sub constval { my $self = shift; return $self->df->sv_at( $self->constval_at ) }
1952             # XS accessors: oproot, depth
1953              
1954             =head2 location
1955              
1956             $location = $cv->location
1957              
1958             Returns C if the line is defined, or C if not.
1959              
1960             =cut
1961              
1962             sub location
1963 0     0   0 {
1964 0         0 my $self = shift;
1965 0         0 my $line = $self->line;
1966             my $file = $self->file;
1967 0 0       0 # line 0 is invalid
1968             return $line ? "$file line $line" : $file;
1969             }
1970              
1971             =head2 is_clone
1972              
1973             =head2 is_cloned
1974              
1975             =head2 is_xsub
1976              
1977             =head2 is_weakoutside
1978              
1979             =head2 is_cvgv_rc
1980              
1981             =head2 is_lexical
1982              
1983             $clone = $cv->is_clone
1984              
1985             $cloned = $cv->is_cloned
1986              
1987             $xsub = $cv->is_xsub
1988              
1989             $weak = $cv->is_weakoutside
1990              
1991             $rc = $cv->is_cvgv_rc
1992              
1993             $lexical = $cv->is_lexical
1994              
1995             Returns the C, C, C, C,
1996             C and C flags.
1997              
1998             =cut
1999              
2000             # XS accessors
2001              
2002             =head2 protosub
2003              
2004             $protosub = $cv->protosub
2005              
2006             Returns the protosub CV, if known, for a closure CV.
2007              
2008             =cut
2009 15792     15792   24034  
  15792         49826  
2010             sub protosub { my $self = shift; return $self->df->sv_at( $self->protosub_at ); }
2011              
2012             =head2 constants
2013              
2014             @svs = $cv->constants
2015              
2016             Returns a list of the SVs used as constants or method names in the code. On
2017             ithreads perl the constants are part of the padlist structure so this list is
2018             constructed from parts of the padlist at loading time.
2019              
2020             =cut
2021              
2022             sub constants
2023 21217     21217   30394 {
2024 21217         37799 my $self = shift;
2025 21217 100       30196 my $df = $self->df;
  47621         81807  
  21217         101508  
2026             return map { $df->sv_at($_) } @{ $self->{consts_at} || [] };
2027             }
2028              
2029             =head2 globrefs
2030              
2031             @svs = $cv->globrefs
2032              
2033             Returns a list of the SVs used as GLOB references in the code. On ithreads
2034             perl the constants are part of the padlist structure so this list is
2035             constructed from parts of the padlist at loading time.
2036              
2037             =cut
2038              
2039             sub globrefs
2040 21216     21216   30188 {
2041 21216         38957 my $self = shift;
2042 21216         28917 my $df = $self->df;
  18355         32040  
  21216         78135  
2043             return map { $df->sv_at($_) } @{ $self->{gvs_at} };
2044             }
2045 0 0   0   0  
  0         0  
2046             sub stashname { my $self = shift; return $self->stash ? $self->stash->stashname : undef }
2047              
2048             sub symname
2049 23     23   41 {
2050             my $self = shift;
2051              
2052 23 50       107 # CvLEXICALs or CVs with non-reified CvGVs may still have a hekname
    100          
2053 0         0 if( defined( my $hekname = $self->hekname ) ) {
2054 0         0 my $stashname = $self->stashname;
2055 0         0 $stashname =~ s/^main:://;
2056             return '&' . $stashname . "::" . $hekname;
2057             }
2058 22         67 elsif( my $glob = $self->glob ) {
2059             return '&' . $glob->stashname;
2060             }
2061 1         5  
2062             return undef;
2063             }
2064              
2065             =head2 padname
2066              
2067             $padname = $cv->padname( $padix )
2068              
2069             Returns the name of the $padix'th lexical variable, or C if it doesn't
2070             have a name.
2071              
2072             The returned padname is a structure of the following fields:
2073              
2074             $name = $padname->name
2075              
2076             $bool = $padname->is_outer
2077             $bool = $padname->is_state
2078             $bool = $padname->is_lvalue
2079             $bool = $padname->is_typed
2080             $bool = $padname->is_our
2081             $bool = $padname->is_field
2082              
2083             =cut
2084              
2085             sub padname
2086 243     243   312 {
2087 243         358 my $self = shift;
2088             my ( $padix ) = @_;
2089 243         489  
2090             return $self->{padnames}[$padix];
2091             }
2092              
2093             =head2 padix_from_padname
2094              
2095             $padix = $cv->padix_from_padname( $padname )
2096              
2097             Returns the index of the first lexical variable with the given pad name, or
2098             C if one does not exist.
2099              
2100             =cut
2101              
2102             sub padix_from_padname
2103 5     5   628 {
2104 5         11 my $self = shift;
2105             my ( $padname ) = @_;
2106 5         10  
2107             my $padnames = $self->{padnames};
2108 5         20  
2109 29         103 foreach my $padix ( 1 .. $#$padnames ) {
2110             my $thisname;
2111 29 100 66     93  
      100        
2112             return $padix if defined $padnames->[$padix] and
2113             defined( $thisname = $padnames->[$padix]->name ) and
2114             $thisname eq $padname;
2115             }
2116 0         0  
2117             return undef;
2118             }
2119              
2120             =head2 max_padix
2121              
2122             $max_padix = $cv->max_padix
2123              
2124             Returns the maximum valid pad index.
2125              
2126             This is typically used to create a list of potential pad indexes, such as
2127              
2128             0 .. $cv->max_padix
2129              
2130             Note that since pad slots may contain things other than lexical variables, not
2131             every pad slot between 0 and this index will necessarily contain a lexical
2132             variable or have a pad name.
2133              
2134             =cut
2135              
2136             sub max_padix
2137 1     1   3 {
2138 1         2 my $self = shift;
  1         7  
2139             return $#{ $self->{padnames} };
2140             }
2141              
2142             =head2 padnames_av
2143              
2144             $padnames_av = $cv->padnames_av
2145              
2146             Returns the AV reference directly which stores the pad names.
2147              
2148             After perl version 5.20, this is no longer used directly and will return
2149             C. The individual pad names themselves can still be found via the
2150             C method.
2151              
2152             =cut
2153              
2154             sub padnames_av
2155 64616     64616   87221 {
2156             my $self = shift;
2157 64616   50     196365  
      0        
2158 0         0 return $self->df->sv_at( $self->padnames_at or return undef )
2159             // croak "${\ $self->desc } PADNAMES is not accessible";
2160             }
2161              
2162             =head2 pads
2163              
2164             @pads = $cv->pads
2165              
2166             Returns a list of the actual pad AVs.
2167              
2168             =cut
2169              
2170             sub pads
2171 5425     5425   6854 {
2172 5425 50       19122 my $self = shift;
  5425         15048  
2173             return $self->{pads} ? @{ $self->{pads} } : ();
2174             }
2175              
2176             =head2 pad
2177              
2178             $pad = $cv->pad( $depth )
2179              
2180             Returns the PAD at the given depth (given by 1-based index).
2181              
2182             =cut
2183              
2184             sub pad
2185 7     7   1011 {
2186 7         16 my $self = shift;
2187 7 50       55 my ( $depth ) = @_;
2188             return $self->{pads} ? $self->{pads}[$depth-1] : undef;
2189             }
2190              
2191             =head2 maybe_lexvar
2192              
2193             $sv = $cv->maybe_lexvar( $padname, $depth )
2194              
2195             I
2196              
2197             Returns the SV on the PAD associated with the given padname, at the
2198             optionally-given depth (1-based index). If I<$depth> is not provided, the
2199             topmost live PAD will be used. If no variable exists of the given name returns
2200             C.
2201              
2202             Used to be called C.
2203              
2204             =cut
2205              
2206             sub maybe_lexvar
2207 3     3   8 {
2208 3         7 my $self = shift;
2209             my ( $padname, $depth ) = @_;
2210 3   66     24  
2211 3 50       11 $depth //= $self->depth;
2212             $depth or croak "Cannot fetch current pad of a non-live CODE";
2213 3         11  
2214             return $self->pad( $depth )->maybe_lexvar( $padname );
2215             }
2216              
2217             *lexvar = \&maybe_lexvar;
2218              
2219             sub desc
2220 12399     12399   60439 {
2221             my $self = shift;
2222 12399         15111  
2223 12399 100       39240 my @flags;
2224 12399 100       20404 push @flags, "PP" if $self->oproot;
2225 12399 100       30404 push @flags, "CONST" if $self->constval;
2226             push @flags, "XS" if $self->is_xsub;
2227 12399 100       24238  
2228 12399 100       22731 push @flags, "closure" if $self->is_cloned;
2229             push @flags, "proto" if $self->is_clone;
2230 12399         17915  
2231 12399         32342 local $" = ",";
2232             return "CODE(@flags)";
2233             }
2234              
2235             sub _outrefs
2236 15791     15791   23572 {
2237 15791         27272 my $self = shift;
2238             my ( $match, $no_desc ) = @_;
2239 15791         51193  
2240             my $pads = $self->{pads};
2241 15791 50       37427  
2242             my $maxdepth = $pads ? scalar @$pads : 0;
2243 15791         35933  
2244             my $have_padlist = defined $self->padlist;
2245 15791         26777  
2246             my @outrefs;
2247 15791         36108  
2248 15791 100 66     52868 my $is_weakoutside = $self->is_weakoutside;
    100          
2249 6487 100       11865 if( $match & ( $is_weakoutside ? STRENGTH_WEAK : STRENGTH_STRONG ) and my $scope = $self->scope ) {
2250 6487 100       14556 my $strength = $is_weakoutside ? "weak" : "strong";
2251             push @outrefs, $no_desc ? ( $strength => $scope ) :
2252             Devel::MAT::SV::Reference( "the scope", $strength => $scope );
2253             }
2254 15791 100 66     50217  
2255 13419 100       35647 if( $match & STRENGTH_WEAK and my $stash = $self->stash ) {
2256             push @outrefs, $no_desc ? ( weak => $stash ) :
2257             Devel::MAT::SV::Reference( "the stash", weak => $stash );
2258             }
2259 15791         53561  
2260 15791 100 66     57781 my $is_strong_gv = $self->is_cvgv_rc;
    100          
2261 15490 100       33139 if( $match & ( $is_strong_gv ? STRENGTH_STRONG : STRENGTH_WEAK ) and my $glob = $self->glob ) {
2262 15490 100       35787 my $strength = $is_strong_gv ? "strong" : "weak";
2263             push @outrefs, $no_desc ? ( $strength => $glob ) :
2264             Devel::MAT::SV::Reference( "the glob", $strength => $glob );
2265             }
2266 15791 100 66     58728  
2267 6798 100       20798 if( $match & STRENGTH_STRONG and my $constval = $self->constval ) {
2268             push @outrefs, $no_desc ? ( strong => $constval ) :
2269             Devel::MAT::SV::Reference( "the constant value", strong => $constval );
2270             }
2271 15791 100 66     59126  
2272 941 100       2712 if( $match & STRENGTH_INFERRED and my $protosub = $self->protosub ) {
2273             push @outrefs, $no_desc ? ( inferred => $protosub ) :
2274             Devel::MAT::SV::Reference( "the protosub", inferred => $protosub );
2275             }
2276              
2277             # Under ithreads, constants and captured GVs are actually stored in the
2278 15791         49970 # first padlist, so they're only here.
2279             my $ithreads = $self->df->ithreads;
2280 15791 50       46711  
    50          
2281 15791 50       32199 if( $match & ( $ithreads ? STRENGTH_INDIRECT : STRENGTH_STRONG ) ) {
2282             my $strength = $ithreads ? "indirect" : "strong";
2283 15791         30051  
2284 33722 50       63183 foreach my $sv ( $self->constants ) {
2285 33722 100       60993 $sv or next;
2286             push @outrefs, $no_desc ? ( $strength => $sv ) :
2287             Devel::MAT::SV::Reference( "a constant", $strength => $sv );
2288 15791         37462 }
2289 12524 50       23677 foreach my $sv ( $self->globrefs ) {
2290 12524 100       23931 $sv or next;
2291             push @outrefs, $no_desc ? ( $strength => $sv ) :
2292             Devel::MAT::SV::Reference( "a referenced glob", $strength => $sv );
2293             }
2294             }
2295 15791 50 33     55380  
2296 0 0       0 if( $match & STRENGTH_STRONG and $have_padlist ) {
2297             push @outrefs, $no_desc ? ( strong => $self->padlist ) :
2298             Devel::MAT::SV::Reference( "the padlist", strong => $self->padlist );
2299             }
2300              
2301             # If we have a PADLIST then its contents are indirect; if not then they
2302 15791 50       37547 # are direct strong
    50          
2303 15791 50       29436 if( $match & ( $have_padlist ? STRENGTH_INDIRECT : STRENGTH_STRONG ) ) {
2304             my $strength = $have_padlist ? "indirect" : "strong";
2305 15791 50       31371  
2306 0 0       0 if( my $padnames_av = $self->padnames_av ) {
2307             push @outrefs, $no_desc ? ( $strength => $padnames_av ) :
2308             Devel::MAT::SV::Reference( "the padnames", $strength => $padnames_av );
2309             }
2310 15791         39219  
2311 6804 100       24569 foreach my $depth ( 1 .. $maxdepth ) {
2312             my $pad = $pads->[$depth-1] or next;
2313 6802 100       17905  
2314             push @outrefs, $no_desc ? ( $strength => $pad ) :
2315             Devel::MAT::SV::Reference( "pad at depth $depth", $strength => $pad );
2316             }
2317             }
2318 15791         62455  
2319             return @outrefs;
2320             }
2321              
2322 9     9   93 package Devel::MAT::SV::IO 0.50;
  9         19  
  9         1016  
2323             use base qw( Devel::MAT::SV );
2324 9     9   62 __PACKAGE__->register_type( 8 );
  9         17  
  9         848  
2325 9     9   70 use constant $CONSTANTS;
  9         27  
  9         5292  
2326             use constant basetype => "IO";
2327              
2328             =head1 Devel::MAT::SV::IO
2329              
2330             Represents an IO handle; an SV type of C.
2331              
2332             =cut
2333              
2334             sub load
2335 126     126   311 {
2336 126         361 my $self = shift;
2337 126         514 my ( $header, $ptrs, $strs ) = @_;
2338             my $df = $self->df;
2339 126         459  
  126         581  
2340             @{$self}{qw( ifileno ofileno )} =
2341             unpack "$df->{uint_fmt}2", $header;
2342              
2343 126   66     342 defined $_ and $_ == $df->{minus_1} and
  126   100     1140  
2344             $_ = -1 for @{$self}{qw( ifileno ofileno )};
2345 126         339  
  126         617  
2346             @{$self}{qw( topgv_at formatgv_at bottomgv_at )} =
2347             @$ptrs;
2348             }
2349              
2350             =head2 ifileno
2351              
2352             =head2 ofileno
2353              
2354             $ifileno = $io->ifileno
2355              
2356             $ofileno = $io->ofileno
2357              
2358             Returns the input or output file numbers.
2359              
2360             =cut
2361 0     0   0  
  0         0  
2362 1     1   8 sub ifileno { my $self = shift; return $self->{ifileno} }
  1         5  
2363             sub ofileno { my $self = shift; return $self->{ofileno} }
2364 36     36   75  
  36         221  
2365 36     36   79 sub topgv { my $self = shift; $self->df->sv_at( $self->{topgv_at} ) }
  36         147  
2366 36     36   58 sub formatgv { my $self = shift; $self->df->sv_at( $self->{formatgv_at} ) }
  36         130  
2367             sub bottomgv { my $self = shift; $self->df->sv_at( $self->{bottomgv_at} ) }
2368 36     36   362  
2369             sub desc { "IO()" }
2370              
2371             sub _outrefs
2372 36     36   94 {
2373 36         116 my $self = shift;
2374             my ( $match, $no_desc ) = @_;
2375 36         68  
2376             my @outrefs;
2377 36 50       115  
2378 36 50       152 if( $match & STRENGTH_STRONG ) {
2379 0 0       0 if( my $gv = $self->topgv ) {
2380             push @outrefs, $no_desc ? ( strong => $gv ) :
2381             Devel::MAT::SV::Reference( "the top GV", strong => $gv );
2382 36 50       162 }
2383 0 0       0 if( my $gv = $self->formatgv ) {
2384             push @outrefs, $no_desc ? ( strong => $gv ) :
2385             Devel::MAT::SV::Reference( "the format GV", strong => $gv );
2386 36 50       131 }
2387 0 0       0 if( my $gv = $self->bottomgv ) {
2388             push @outrefs, $no_desc ? ( strong => $gv ) :
2389             Devel::MAT::SV::Reference( "the bottom GV", strong => $gv );
2390             }
2391             }
2392 36         117  
2393             return @outrefs;
2394             }
2395              
2396 9     9   76 package Devel::MAT::SV::LVALUE 0.50;
  9         19  
  9         963  
2397             use base qw( Devel::MAT::SV );
2398 9     9   59 __PACKAGE__->register_type( 9 );
  9         34  
  9         916  
2399 9     9   69 use constant $CONSTANTS;
  9         17  
  9         3605  
2400             use constant basetype => "LV";
2401              
2402             sub load
2403 1     1   6 {
2404 1         5 my $self = shift;
2405 1         7 my ( $header, $ptrs, $strs ) = @_;
2406             my $df = $self->df;
2407 1         13  
2408             ( $self->{type}, $self->{off}, $self->{len} ) =
2409             unpack "a1 $df->{uint_fmt}2", $header;
2410 1         6  
2411             ( $self->{targ_at} ) =
2412             @$ptrs;
2413             }
2414 1     1   4  
  1         5  
2415 0     0   0 sub lvtype { my $self = shift; return $self->{type} }
  0         0  
2416 0     0   0 sub off { my $self = shift; return $self->{off} }
  0         0  
2417 0     0   0 sub len { my $self = shift; return $self->{len} }
  0         0  
2418             sub target { my $self = shift; return $self->df->sv_at( $self->{targ_at} ) }
2419 0     0   0  
2420             sub desc { "LVALUE()" }
2421              
2422             sub _outrefs
2423 0     0   0 {
2424 0         0 my $self = shift;
2425             my ( $match, $no_desc ) = @_;
2426 0         0  
2427             my @outrefs;
2428 0 0 0     0  
2429 0 0       0 if( $match & STRENGTH_STRONG and my $sv = $self->target ) {
2430             push @outrefs, $no_desc ? ( strong => $sv ) :
2431             Devel::MAT::SV::Reference( "the target", strong => $sv );
2432             }
2433 0         0  
2434             return @outrefs;
2435             }
2436              
2437 9     9   65 package Devel::MAT::SV::REGEXP 0.50;
  9         17  
  9         882  
2438 9     9   60 use base qw( Devel::MAT::SV );
  9         27  
  9         1114  
2439             use constant basetype => "REGEXP";
2440             __PACKAGE__->register_type( 10 );
2441       5009      
2442             sub load {}
2443 1429     1429   7678  
2444             sub desc { "REGEXP()" }
2445 1432     1432   2546  
2446             sub _outrefs { () }
2447              
2448 9     9   69 package Devel::MAT::SV::FORMAT 0.50;
  9         18  
  9         989  
2449 9     9   70 use base qw( Devel::MAT::SV );
  9         14  
  9         1110  
2450             use constant basetype => "PVFM";
2451             __PACKAGE__->register_type( 11 );
2452       0      
2453             sub load {}
2454 0     0   0  
2455             sub desc { "FORMAT()" }
2456 0     0   0  
2457             sub _outrefs { () }
2458              
2459 9     9   61 package Devel::MAT::SV::INVLIST 0.50;
  9         16  
  9         863  
2460 9     9   60 use base qw( Devel::MAT::SV );
  9         16  
  9         1151  
2461             use constant basetype => "INVLIST";
2462             __PACKAGE__->register_type( 12 );
2463       553      
2464             sub load {}
2465 158     158   1064  
2466             sub desc { "INVLIST()" }
2467 163     163   357  
2468             sub _outrefs { () }
2469              
2470             # A hack to compress files
2471 9     9   64 package Devel::MAT::SV::_UNDEFSV 0.50;
  9         28  
  9         3621  
2472             use base qw( Devel::MAT::SV::SCALAR );
2473             __PACKAGE__->register_type( 13 );
2474              
2475             sub load
2476 159703     159703   233334 {
2477             my $self = shift;
2478 159703         251223  
2479             bless $self, "Devel::MAT::SV::SCALAR";
2480 159703         400794  
2481             $self->_set_scalar_fields( 0, 0, 0,
2482             "", 0,
2483             0,
2484             );
2485             }
2486              
2487 9     9   74 package Devel::MAT::SV::_YESSV 0.50;
  9         27  
  9         3448  
2488             use base qw( Devel::MAT::SV::BOOL );
2489             __PACKAGE__->register_type( 14 );
2490              
2491             sub load
2492 0     0     {
2493             my $self = shift;
2494 0            
2495             bless $self, "Devel::MAT::SV::BOOL";
2496 0            
2497             $self->_set_scalar_fields( 0x01, 1, 1.0,
2498             "1", 1,
2499             0,
2500             );
2501             }
2502              
2503 9     9   68 package Devel::MAT::SV::_NOSV 0.50;
  9         19  
  9         3366  
2504             use base qw( Devel::MAT::SV::BOOL );
2505             __PACKAGE__->register_type( 15 );
2506              
2507             sub load
2508 0     0     {
2509             my $self = shift;
2510 0            
2511             bless $self, "Devel::MAT::SV::BOOL";
2512 0            
2513             $self->_set_scalar_fields( 0x01, 0, 0,
2514             "", 0,
2515             0,
2516             );
2517             }
2518              
2519 9     9   67 package Devel::MAT::SV::OBJECT 0.50;
  9         59  
  9         1016  
2520             use base qw( Devel::MAT::SV );
2521 9     9   72 __PACKAGE__->register_type( 16 );
  9         16  
  9         1024  
2522 9     9   72 use constant $CONSTANTS;
  9         26  
  9         5975  
2523             use constant basetype => "OBJ";
2524              
2525             =head1 Devel::MAT::SV::OBJECT
2526              
2527             Represents an object instance; an SV of type C. These are only
2528             present in files from perls with C.
2529              
2530             =cut
2531              
2532             sub load
2533 0     0     {
2534 0           my $self = shift;
2535 0           my ( $header, $ptrs, $strs ) = @_;
2536             my $df = $self->df;
2537 0            
2538             my ( $n ) =
2539             unpack "$df->{uint_fmt} a*", $header;
2540 0 0          
2541 0           my @fields_at = $n ? $df->_read_ptrs( $n ) : ();
2542             $self->_set_object_fields( \@fields_at );
2543             }
2544              
2545             =head2 fields
2546              
2547             @svs = $obj->fields
2548              
2549             Returns all the values of all the fields in a list.
2550              
2551             Note that to find the names of the fields you'll have to enquire with the
2552             class
2553              
2554             =cut
2555              
2556             sub fields
2557 0     0     {
2558             my $self = shift;
2559 0            
2560 0 0         my $n = $self->n_fields;
2561             return $n unless wantarray;
2562 0            
2563 0           my $df = $self->df;
  0            
2564             return map { $df->sv_at( $self->field_at( $_ ) ) } 0 .. $n-1;
2565             }
2566              
2567             =head2 field
2568              
2569             $sv = $obj->field( $name_or_fieldix )
2570              
2571             Returns the value of the given field; which may be specified by name or
2572             index directly.
2573              
2574             =cut
2575              
2576             sub field
2577 0     0     {
2578 0           my $self = shift;
2579             my ( $name_or_fieldix ) = @_;
2580 0            
2581 0 0         my $fieldix;
2582 0           if( $name_or_fieldix =~ m/^\d+$/ ) {
2583             $fieldix = $name_or_fieldix;
2584             }
2585 0           else {
2586             $fieldix = $self->blessed->field( $name_or_fieldix )->fieldix;
2587             }
2588 0            
2589             return $self->df->sv_at( $self->field_at( $fieldix ) );
2590             }
2591              
2592             sub desc
2593 0     0     {
2594             my $self = shift;
2595 0            
2596             return "OBJ()";
2597             }
2598              
2599             sub _outrefs
2600 0     0     {
2601 0           my $self = shift;
2602             my ( $match, $no_desc ) = @_;
2603 0            
2604             my $n = $self->n_fields;
2605 0            
2606             my @outrefs;
2607 0            
2608 0 0         foreach my $field ( $self->blessed->fields ) {
2609             my $sv = $self->field( $field->fieldix ) or next;
2610 0 0          
2611             my $name = $no_desc ? undef :
2612 0 0         "the " . Devel::MAT::Cmd->format_note( $field->name, 1 ) . " field";
2613 0 0         if( $match & STRENGTH_STRONG ) {
2614             push @outrefs, $no_desc ? ( strong => $sv ) :
2615             Devel::MAT::SV::Reference( $name, strong => $sv );
2616 0 0 0       }
      0        
      0        
2617 0 0         if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
2618             push @outrefs, $no_desc ? ( indirect => $rv ) :
2619             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
2620             }
2621             }
2622 0            
2623             return @outrefs;
2624             }
2625              
2626 9     9   78 package Devel::MAT::SV::CLASS 0.50;
  9         15  
  9         2947  
2627             use base qw( Devel::MAT::SV::STASH );
2628 9     9   78 __PACKAGE__->register_type( 17 );
  9         19  
  9         758  
2629             use constant $CONSTANTS;
2630 9     9   61  
  9         19  
  9         658  
2631             use Carp;
2632 9     9   62  
  9         173  
  9         58  
2633             use Struct::Dumb 0.07 qw( readonly_struct );
2634             readonly_struct Field => [qw( fieldix name )];
2635 9     9   687  
  9         25  
  9         7347  
2636             use List::Util qw( first );
2637              
2638             =head1 Devel::MAT::SV::CLASS
2639              
2640             Represents a class; a sub-type of stash for implementing object classes. These
2641             are only present in files from perls with C.
2642              
2643             =cut
2644              
2645             sub load
2646 0     0     {
2647 0           my $self = shift;
2648 0           my ( $header, $ptrs, $strs ) = @_;
2649             my $df = $self->df;
2650 0            
  0            
2651             my ( $stash_bytes, $stash_ptrs, $stash_strs ) = @{ $df->{sv_sizes}[6] };
2652 0            
2653             $self->SUPER::load(
2654             substr( $header, 0, $stash_bytes, "" ),
2655             [ splice @$ptrs, 0, $stash_ptrs ],
2656             [ splice @$strs, 0, $stash_strs ],
2657             );
2658 0            
  0            
2659             @{$self}{qw( adjust_blocks_at )} =
2660             @$ptrs;
2661 0            
2662             while( my $type = $df->_read_u8 ) {
2663 0           match( $type : == ) {
  0            
2664 0 0         case( 1 ) { push @{ $self->{fields} }, [ $df->_read_uint, $df->_read_str ] }
2665 0           default {
2666             die "TODO: unhandled CLASSx type $type";
2667             }
2668             }
2669             }
2670             }
2671 0     0      
  0            
2672             sub adjust_blocks { my $self = shift; return $self->df->sv_at( $self->{adjust_blocks_at} ) }
2673              
2674             =head2 fields
2675              
2676             @fields = $class->fields
2677              
2678             Returns a list of the field definitions of the class, in declaration order.
2679             Each is a structure whose form is given below.
2680              
2681             =cut
2682              
2683             sub fields
2684 0     0     {
2685 0           my $self = shift;
  0            
  0            
2686             return map { Field( @$_ ) } @{ $self->{fields} };
2687             }
2688              
2689             =head2 field
2690              
2691             $field = $class->field( $name_or_fieldix )
2692              
2693             Returns the field definition of the given field; which may be specified by
2694             name or index directly. Throws an exception if none such exists.
2695              
2696             The returned field is a structure of the following fields:
2697              
2698             $fieldix = $field->fieldix
2699             $name = $field->name
2700              
2701             =head2 maybe_field
2702              
2703             $field = $class->maybe_field( $name_or_fieldix )
2704              
2705             I
2706              
2707             Similar to L but returns undef if none such exists.
2708              
2709             =cut
2710              
2711             sub maybe_field
2712 0     0     {
2713 0           my $self = shift;
2714             my ( $name_or_fieldix ) = @_;
2715 0 0          
2716 0     0     if( $name_or_fieldix =~ m/^\d+$/ ) {
  0            
2717             return first { $_->fieldix == $name_or_fieldix } $self->fields;
2718             }
2719 0     0     else {
  0            
2720             return first { $_->name eq $name_or_fieldix } $self->fields
2721             }
2722             }
2723              
2724             sub field
2725 0     0     {
2726 0   0       my $self = shift;
2727 0           return $self->maybe_field( @_ ) // do {
2728 0 0         my ( $name_or_fieldix ) = @_;
2729 0           croak "No field at index $name_or_fieldix" if $name_or_fieldix =~ m/^\d+$/;
2730             croak "No field named '$name_or_fieldix'";
2731             };
2732             }
2733              
2734             sub _outrefs
2735 0     0     {
2736 0           my $self = shift;
2737             my ( $match, $no_desc ) = @_;
2738 0            
2739             my @outrefs = $self->SUPER::_outrefs( @_ );
2740 0 0          
2741 0 0         if( $match & STRENGTH_STRONG ) {
2742 0 0         if( my $sv = $self->adjust_blocks ) {
2743             push @outrefs, $no_desc ? ( strong => $sv ) :
2744             Devel::MAT::SV::Reference( "the ADJUST blocks AV", strong => $sv );
2745             }
2746             }
2747 0            
2748             return @outrefs;
2749             }
2750              
2751             # A "SV" type that isn't really an SV, but has many of the same methods. These
2752             # aren't created by core perl, but are used by XS extensions
2753 9     9   72 package Devel::MAT::SV::C_STRUCT 0.50;
  9         47  
  9         964  
2754             use base qw( Devel::MAT::SV );
2755 9     9   60 __PACKAGE__->register_type( 0x7F );
  9         15  
  9         968  
2756             use constant $CONSTANTS;
2757 9         759 use constant {
2758             FIELD_PTR => 0x00,
2759             FIELD_BOOL => 0x01,
2760             FIELD_U8 => 0x02,
2761             FIELD_U32 => 0x03,
2762 9     9   76 FIELD_UINT => 0x04,
  9         38  
2763 9     9   52 };
  9         19  
  9         606  
2764 9     9   83 use Carp;
  9         19  
  9         8168  
2765             use List::Util qw( first );
2766              
2767             =head1 Devel::MAT::SV::C_STRUCT
2768              
2769             Represents a C-level c type.
2770              
2771             =cut
2772              
2773             sub desc
2774 0     0     {
2775 0           my $self = shift;
2776             my $typename = $self->structtype->name;
2777 0            
2778             "C_STRUCT($typename)";
2779             }
2780              
2781             sub load
2782 0     0     {
2783 0           my $self = shift;
2784             my ( $fields ) = @_;
2785 0            
2786             my $df = $self->df;
2787 0            
2788             my @vals;
2789 0            
2790 0           foreach my $field ( @$fields ) {
2791             push @vals, my $type = $field->type;
2792 0 0 0        
    0          
    0          
    0          
2793 0           if( $type == FIELD_PTR ) {
2794             push @vals, $df->_read_ptr;
2795             }
2796 0           elsif( $type == FIELD_BOOL or $type == FIELD_U8 ) {
2797             push @vals, $df->_read_u8;
2798             }
2799 0           elsif( $type == FIELD_U32 ) {
2800             push @vals, $df->_read_u32;
2801             }
2802 0           elsif( $type == FIELD_UINT ) {
2803             push @vals, $df->_read_uint;
2804             }
2805 0           else {
2806             croak "TODO: load struct field type = $type\n";
2807             }
2808             }
2809 0            
2810             $self->_set_struct_fields( @vals );
2811             }
2812              
2813             =head2 fields
2814              
2815             @kvlist = $struct->fields
2816              
2817             Returns an even-sized name/value list of all the field values stored by the
2818             struct; each preceeded by its field type structure.
2819              
2820             =cut
2821              
2822             sub fields
2823 0     0     {
2824             my $self = shift;
2825 0            
2826             my $df = $self->df;
2827 0            
2828             my $fields = $self->structtype->fields;
2829              
2830 0           return map {
  0            
2831             my $field = $fields->[$_];
2832 0 0          
2833 0           if( $field->type == FIELD_PTR ) {
2834             $field => $df->sv_at( $self->field( $_ ) )
2835             }
2836 0           else {
2837             $field => $self->field( $_ );
2838             }
2839             } 0 .. $#$fields;
2840             }
2841              
2842             =head2 field_named
2843              
2844             $val = $struct->field_named( $name )
2845              
2846             Looks for a field whose name is exactly that given, and returns its value.
2847              
2848             Throws an exception if the struct has no such field of that name.
2849              
2850             =head2 maybe_field_named
2851              
2852             $val = $struct->maybe_field_named( $name )
2853              
2854             I
2855              
2856             As L but returns C if there is no such field.
2857              
2858             =cut
2859              
2860             sub maybe_field_named
2861 0     0     {
2862 0           my $self = shift;
2863             my ( $name ) = @_;
2864 0            
2865             my $fields = $self->structtype->fields;
2866 0 0   0      
  0            
2867             defined( my $idx = first { $fields->[$_]->name eq $name } 0 .. $#$fields )
2868             or return undef;
2869 0            
2870             my $field = $fields->[$idx];
2871 0 0          
2872 0           if( $field->type == FIELD_PTR ) {
2873             return $self->df->sv_at( $self->field( $idx ) );
2874             }
2875 0           else {
2876             return $self->field( $idx );
2877             }
2878             }
2879              
2880             sub field_named
2881 0     0     {
2882 0           my $self = shift;
2883             my ( $name ) = @_;
2884 0   0        
2885             return $self->maybe_field_named( $name ) // croak "No field named $name";
2886             }
2887              
2888             =head2 structtype
2889              
2890             $structtype = $struct->structtype
2891              
2892             Returns a metadata structure describing the type of the struct itself.
2893              
2894             Has the following named accessors
2895              
2896             =over 4
2897              
2898             =item name => STRING
2899              
2900             The name of the struct type, as given by the dumpfile.
2901              
2902             =item fields => ARRAY[ Field ]
2903              
2904             An ARRAY reference containing the definitions of each field in turn
2905              
2906             =back
2907              
2908             =cut
2909              
2910             sub structtype
2911 0     0     {
2912 0           my $self = shift;
2913             return $self->df->structtype( $self->structid );
2914             }
2915              
2916             sub _outrefs
2917 0     0     {
2918 0           my $self = shift;
2919             my ( $match, $no_desc ) = @_;
2920 0 0          
2921             return unless $match & STRENGTH_STRONG;
2922 0            
2923             my $df = $self->df;
2924 0            
2925             my @outrefs;
2926 0            
2927 0           my $fields = $self->structtype->fields;
2928 0           foreach my $idx ( 0 .. $#$fields ) {
2929 0 0         my $field = $fields->[$idx];
2930             $field->type == FIELD_PTR or next; # Is PTR
2931 0 0          
2932             my $sv = $df->sv_at( $self->field( $idx ) ) or next;
2933 0 0          
2934             push @outrefs, $no_desc ? ( strong => $sv ) :
2935             Devel::MAT::SV::Reference( $field->name, strong => $sv );
2936             }
2937 0            
2938             return @outrefs;
2939             }
2940              
2941             =head1 AUTHOR
2942              
2943             Paul Evans
2944              
2945             =cut
2946              
2947             0x55AA;