File Coverage

blib/lib/Devel/MAT/SV.pm
Criterion Covered Total %
statement 788 1095 71.9
branch 282 482 58.5
condition 72 146 49.3
subroutine 191 274 69.7
pod 16 22 72.7
total 1349 2019 66.8


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.49;
7              
8 9     9   93 use v5.14;
  9         26  
9 9     9   39 use warnings;
  9         13  
  9         211  
10              
11 9     9   35 use Carp;
  9         11  
  9         368  
12 9     9   41 use Scalar::Util qw( weaken );
  9         13  
  9         358  
13              
14 9     9   585 use Syntax::Keyword::Match;
  9         1659  
  9         60  
15              
16             # Load XS code
17             require Devel::MAT;
18              
19 9     9   522 use constant immortal => 0;
  9         22  
  9         821  
20              
21 9     9   44 use List::Util qw( first );
  9         18  
  9         514  
22              
23 9     9   5466 use Struct::Dumb 0.07 qw( readonly_struct );
  9         20145  
  9         45  
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   1027 $CONSTANTS = {
42             STRENGTH_STRONG => (1 << 0),
43             STRENGTH_WEAK => (1 << 1),
44             STRENGTH_INDIRECT => (1 << 2),
45             STRENGTH_INFERRED => (1 << 3),
46             };
47 9         32 $CONSTANTS->{STRENGTH_DIRECT} = $CONSTANTS->{STRENGTH_STRONG}|$CONSTANTS->{STRENGTH_WEAK};
48 9         163 $CONSTANTS->{STRENGTH_ALL} = $CONSTANTS->{STRENGTH_STRONG}|$CONSTANTS->{STRENGTH_WEAK}|$CONSTANTS->{STRENGTH_INDIRECT}|$CONSTANTS->{STRENGTH_INFERRED};
49             }
50 9     9   188 use constant $CONSTANTS;
  9         25  
  9         1286  
51              
52             my %types;
53             sub register_type
54             {
55 171     171 0 353 $types{$_[1]} = $_[0];
56             # generate the ->type constant method
57 171         453 ( my $typename = $_[0] ) =~ s/^Devel::MAT::SV:://;
58 9     9   59 no strict 'refs';
  9         21  
  9         13625  
59 171 100   0   288 *{"$_[0]::type"} = sub () { $typename } unless defined *{"$_[0]::type"}{CODE};
  162         464  
  0         0  
  171         1163  
60             }
61              
62             sub new
63             {
64 539875     539875 0 625365 shift;
65 539875         729631 my ( $type, $df, $header, $ptrs, $strs ) = @_;
66              
67 539875 50       1001326 my $class = $types{$type} or croak "Cannot load unknown SV type $type";
68              
69 539875         845518 my $self = bless {}, $class;
70              
71 539875         2447493 $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 539875         1000315 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 171260     171260 1 186710 my $self = shift;
167 171260         409139 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 28038     28038 1 30593 my $self = shift;
241 28038 100       141515 return unless my $magic = $self->{magic};
242              
243 449         867 my $df = $self->df;
244             return map {
245 449         915 my ( undef, undef, $obj_at, $ptr_at ) = @$_;
  449         895  
246 449 100       1260 ( $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 17 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 8 my $self = shift;
287 4         13 return $self->{rootname};
288             }
289              
290             # internal
291             sub more_magic
292             {
293 40611     40611 0 52341 my $self = shift;
294 40611         61078 my ( $type, $flags, $obj_at, $ptr_at, $vtbl_ptr ) = @_;
295              
296 40611         44067 push @{ $self->{magic} }, [ $type => $flags, $obj_at, $ptr_at, $vtbl_ptr ];
  40611         165959  
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 171271     171271   196608 my $self = shift;
368 171271         245992 my ( $match, $no_desc ) = @_;
369              
370             # In scalar context we're just counting so we might as well count just SVs
371 171271   66     263718 $no_desc ||= !wantarray;
372              
373 171271         309572 my @outrefs = $self->_outrefs( $match, $no_desc );
374              
375 171271 100 100     405739 if( $match & STRENGTH_WEAK and my $blessed = $self->blessed ) {
376 1399 100       3703 push @outrefs, $no_desc ? ( weak => $blessed ) :
377             Reference( "the bless package", weak => $blessed );
378             }
379              
380 171271 100       211630 foreach my $mg ( @{ $self->{magic} || [] } ) {
  171271         514499  
381 16672         52004 my ( $type, $flags, $obj_at, $ptr_at ) = @$mg;
382              
383 16672 100       39975 if( my $obj = $self->df->sv_at( $obj_at ) ) {
384 15029         22623 my $is_strong = ( $flags & 0x01 );
385 15029 100       37490 if( $match & ( $is_strong ? STRENGTH_STRONG : STRENGTH_WEAK ) ) {
    50          
386 15029 100       27574 my $strength = $is_strong ? "strong" : "weak";
387 15029 100       43677 push @outrefs, $no_desc ? ( $strength => $obj ) :
388             Reference( "'$type' magic object", $strength => $obj );
389             }
390             }
391              
392 16672 100 66     71752 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 171271 50       199712 foreach my $ann ( @{ $self->{annotations} || [] } ) {
  171271         375517  
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 171271 50       263629 return @outrefs / 2 if !wantarray;
407 171271         1159734 return @outrefs;
408             }
409              
410 171255     171255 1 270539 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 34 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 164 sub outrefs_direct { $_[0]->_outrefs_matching( STRENGTH_DIRECT, $_[1] ) }
448 1     1 1 1908 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 538 my $self = shift;
474 2         6 my ( $name ) = @_;
475              
476 2     3   18 return first { $_->name eq $name } $self->outrefs;
  3         14  
477             }
478              
479             sub outref_named
480             {
481 1     1 1 1793 my $self = shift;
482 1         3 my ( $name ) = @_;
483              
484 1   33     62 return $self->maybe_outref_named( $name ) // croak "No outref named $name";
485             }
486              
487             =head1 IMMORTAL SVs
488              
489             Three special SV objects exist outside of the heap, to represent C and
490             boolean true and false. They are
491              
492             =over 4
493              
494             =item * Devel::MAT::SV::UNDEF
495              
496             =item * Devel::MAT::SV::YES
497              
498             =item * Devel::MAT::SV::NO
499              
500             =back
501              
502             =cut
503              
504             package Devel::MAT::SV::Immortal 0.49;
505 9     9   68 use base qw( Devel::MAT::SV );
  9         12  
  9         1227  
506 9     9   54 use constant immortal => 1;
  9         15  
  9         534  
507 9     9   49 use constant basetype => "SV";
  9         15  
  9         1072  
508             sub new {
509 21     21   33 my $class = shift;
510 21         34 my ( $df, $addr ) = @_;
511 21         47 my $self = bless {}, $class;
512 21         248 $self->_set_core_fields( 0, $df, $addr, 0, 0, 0 );
513 21         73 return $self;
514             }
515 3     3   6 sub _outrefs { () }
516              
517             package Devel::MAT::SV::UNDEF 0.49;
518 9     9   61 use base qw( Devel::MAT::SV::Immortal );
  9         13  
  9         3209  
519 0     0   0 sub desc { "UNDEF" }
520 1554     1554   4771 sub type { "UNDEF" }
521              
522             package Devel::MAT::SV::YES 0.49;
523 9     9   64 use base qw( Devel::MAT::SV::Immortal );
  9         14  
  9         3023  
524 0     0   0 sub desc { "YES" }
525 945     945   2621 sub type { "SCALAR" }
526              
527             # Pretend to be 1 / "1"
528 0     0   0 sub uv { 1 }
529 0     0   0 sub iv { 1 }
530 0     0   0 sub nv { 1.0 }
531 0     0   0 sub pv { "1" }
532 0     0   0 sub rv { undef }
533 0     0   0 sub is_weak { '' }
534              
535             package Devel::MAT::SV::NO 0.49;
536 9     9   77 use base qw( Devel::MAT::SV::Immortal );
  9         17  
  9         2964  
537 0     0   0 sub desc { "NO" }
538 0     0   0 sub type { "SCALAR" }
539              
540             # Pretend to be 0 / ""
541 0     0   0 sub uv { 0 }
542 0     0   0 sub iv { 0 }
543 0     0   0 sub nv { 0.0 }
544 0     0   0 sub pv { "0" }
545 0     0   0 sub rv { undef }
546 0     0   0 sub is_weak { '' }
547              
548             package Devel::MAT::SV::Unknown 0.49;
549 9     9   60 use base qw( Devel::MAT::SV );
  9         38  
  9         1153  
550             __PACKAGE__->register_type( 0xff );
551              
552 0     0   0 sub desc { "UNKNOWN" }
553              
554       0     sub _outrefs {}
555              
556             package Devel::MAT::SV::GLOB 0.49;
557 9     9   55 use base qw( Devel::MAT::SV );
  9         13  
  9         702  
558             __PACKAGE__->register_type( 1 );
559 9     9   48 use constant $CONSTANTS;
  9         30  
  9         760  
560 9     9   49 use constant basetype => "GV";
  9         22  
  9         7900  
561              
562             =head1 Devel::MAT::SV::GLOB
563              
564             Represents a glob; an SV of type C.
565              
566             =cut
567              
568             sub load
569             {
570 50390     50390   69036 my $self = shift;
571 50390         72818 my ( $header, $ptrs, $strs ) = @_;
572 50390         85166 my $df = $self->df;
573              
574 50390         96314 my ( $line ) =
575             unpack "$df->{uint_fmt}", $header;
576              
577             $self->_set_glob_fields(
578 50390         68128 @{$ptrs}[0..7],
  50390         226017  
579             $line, $strs->[1],
580             $strs->[0],
581             );
582             }
583              
584             sub _fixup
585             {
586 50390     50390   53763 my $self = shift;
587              
588 50390   66     62832 $_ and $_->_set_glob_at( $self->addr ) for $self->scalar, $self->array, $self->hash, $self->code;
589             }
590              
591             =head2 file
592              
593             =head2 line
594              
595             =head2 location
596              
597             $file = $gv->file
598              
599             $line = $gv->line
600              
601             $location = $gv->location
602              
603             Returns the filename, line number, or combined location (C)
604             that the GV first appears at.
605              
606             =head2 name
607              
608             $name = $gv->name
609              
610             Returns the value of the C field, for named globs.
611              
612             =cut
613              
614             # XS accessors
615              
616             sub location
617             {
618 0     0   0 my $self = shift;
619 0         0 my $file = $self->file;
620 0         0 my $line = $self->line;
621 0 0       0 defined $file ? "$file line $line" : undef
622             }
623              
624             =head2 stash
625              
626             $stash = $gv->stash
627              
628             Returns the stash to which the GV belongs.
629              
630             =cut
631              
632 27     27   37 sub stash { my $self = shift; $self->df->sv_at( $self->stash_at ) }
  27         104  
633              
634             =head2 scalar
635              
636             =head2 array
637              
638             =head2 hash
639              
640             =head2 code
641              
642             =head2 egv
643              
644             =head2 io
645              
646             =head2 form
647              
648             $sv = $gv->scalar
649              
650             $av = $gv->array
651              
652             $hv = $gv->hash
653              
654             $cv = $gv->code
655              
656             $gv = $gv->egv
657              
658             $io = $gv->io
659              
660             $form = $gv->form
661              
662             Return the SV in the various glob slots.
663              
664             =cut
665              
666 91097     91097   100307 sub scalar { my $self = shift; $self->df->sv_at( $self->scalar_at ) }
  91097         294314  
667 91092     91092   102018 sub array { my $self = shift; $self->df->sv_at( $self->array_at ) }
  91092         205044  
668 91420     91420   99059 sub hash { my $self = shift; $self->df->sv_at( $self->hash_at ) }
  91420         193241  
669 91097     91097   110332 sub code { my $self = shift; $self->df->sv_at( $self->code_at ) }
  91097         191286  
670 33832     33832   39434 sub egv { my $self = shift; $self->df->sv_at( $self->egv_at ) }
  33832         77485  
671 40696     40696   52397 sub io { my $self = shift; $self->df->sv_at( $self->io_at ) }
  40696         96943  
672 40695     40695   44701 sub form { my $self = shift; $self->df->sv_at( $self->form_at ) }
  40695         92549  
673              
674             sub stashname
675             {
676 27     27   37 my $self = shift;
677 27         65 my $name = $self->name;
678 27         74 $name =~ s(^([\x00-\x1f])){"^" . chr(64 + ord $1)}e;
  0         0  
679 27         67 return $self->stash->stashname . "::" . $name;
680             }
681              
682             sub desc
683             {
684 14398     14398   57176 my $self = shift;
685 14398         15677 my $sigils = "";
686 14398 100       19433 $sigils .= '$' if $self->scalar;
687 14398 100       21481 $sigils .= '@' if $self->array;
688 14398 100       21009 $sigils .= '%' if $self->hash;
689 14398 100       19633 $sigils .= '&' if $self->code;
690 14398 100       21434 $sigils .= '*' if $self->egv;
691 14398 100       21535 $sigils .= 'I' if $self->io;
692 14398 50       19934 $sigils .= 'F' if $self->form;
693              
694 14398         29674 return "GLOB($sigils)";
695             }
696              
697             sub _outrefs
698             {
699 19434     19434   26242 my $self = shift;
700 19434         34121 my ( $match, $no_desc ) = @_;
701              
702 19434         23236 my @outrefs;
703              
704 19434 50       41771 if( $match & STRENGTH_STRONG ) {
705 19434         30934 foreach my $slot (qw( scalar array hash code io form )) {
706 116604 100       242781 my $sv = $self->$slot or next;
707 18518 100       63244 push @outrefs, $no_desc ? ( strong => $sv ) :
708             Devel::MAT::SV::Reference( "the $slot", strong => $sv );
709             }
710             }
711              
712 19434 100       33731 if( my $egv = $self->egv ) {
713             # the egv is weakref if if it points back to itself
714 19426         32949 my $egv_is_self = $egv == $self;
715              
716 19426 100       45317 if( $match & ( $egv_is_self ? STRENGTH_WEAK : STRENGTH_STRONG ) ) {
    50          
717 19426 100       30574 my $strength = $egv_is_self ? "weak" : "strong";
718 19426 100       43012 push @outrefs, $no_desc ? ( $strength => $egv ) :
719             Devel::MAT::SV::Reference( "the egv", $strength => $egv );
720             }
721             }
722              
723 19434         43496 foreach my $saved ( @{ $self->{saved} } ) {
  19434         50186  
724 4         22 my $sv = $self->df->sv_at( $saved->[1] );
725              
726 4 50       32 push @outrefs, $no_desc ? ( inferred => $sv ) :
727             Devel::MAT::SV::Reference( "saved value of " . Devel::MAT::Cmd->format_note( $saved->[0] ) . " slot",
728             "inferred", $sv );
729             }
730              
731 19434         46133 return @outrefs;
732             }
733              
734             sub _more_saved
735             {
736 5     5   8 my $self = shift;
737 5         7 my ( $slot, $addr ) = @_;
738              
739 5         6 push @{ $self->{saved} }, [ $slot => $addr ];
  5         19  
740             }
741              
742             package Devel::MAT::SV::SCALAR 0.49;
743 9     9   82 use base qw( Devel::MAT::SV );
  9         16  
  9         819  
744             __PACKAGE__->register_type( 2 );
745 9     9   53 use constant $CONSTANTS;
  9         20  
  9         720  
746 9     9   51 use constant basetype => "SV";
  9         20  
  9         6567  
747              
748             =head1 Devel::MAT::SV::SCALAR
749              
750             Represents a non-referential scalar value; an SV of any of the types up to and
751             including C (that is, C, C, C, C, C or
752             C). This includes all numbers, integers and floats, strings, and dualvars
753             containing multiple parts.
754              
755             =cut
756              
757             sub load
758             {
759 204622     204622   254970 my $self = shift;
760 204622         272665 my ( $header, $ptrs, $strs ) = @_;
761 204622         323178 my $df = $self->df;
762              
763 204622         667830 my ( $flags, $uv, $nvbytes, $pvlen ) =
764             unpack "C $df->{uint_fmt} A$df->{nv_len} $df->{uint_fmt}", $header;
765 204622         351815 my $nv = unpack "$df->{nv_fmt}", $nvbytes;
766              
767             # $strs->[0] will be swiped
768              
769 204622         429997 $self->_set_scalar_fields( $flags, $uv, $nv,
770             $strs->[0], $pvlen,
771             $ptrs->[0], # OURSTASH
772             );
773              
774             # $strs->[0] is now undef
775              
776 204622         226111 $flags &= ~0x1f;
777 204622 50       421346 $flags and die sprintf "Unrecognised SCALAR flags %02x\n", $flags;
778             }
779              
780             =head2 uv
781              
782             $uv = $sv->uv
783              
784             Returns the integer numeric portion as an unsigned value, if valid, or C.
785              
786             =head2 iv
787              
788             $iv = $sv->iv
789              
790             Returns the integer numeric portion as a signed value, if valid, or C.
791              
792             =head2 nv
793              
794             $nv = $sv->nv
795              
796             Returns the floating numeric portion, if valid, or C.
797              
798             =head2 pv
799              
800             $pv = $sv->pv
801              
802             Returns the string portion, if valid, or C.
803              
804             =head2 pvlen
805              
806             $pvlen = $sv->pvlen
807              
808             Returns the length of the string portion, if valid, or C.
809              
810             =cut
811              
812             # XS accessors
813              
814             =head2 qq_pv
815              
816             $str = $sv->qq_pv( $maxlen )
817              
818             Returns the PV string, if defined, suitably quoted. If C<$maxlen> is defined
819             and the PV is longer than this, it is truncated and C<...> is appended after
820             the containing quote marks.
821              
822             =cut
823              
824             sub qq_pv
825             {
826 5     5   17 my $self = shift;
827 5         8 my ( $maxlen ) = @_;
828              
829 5 50       46 defined( my $pv = $self->pv ) or return undef;
830 5 100 66     23 $pv = substr( $pv, 0, $maxlen ) if defined $maxlen and $maxlen < length $pv;
831              
832 5         15 my $truncated = $self->pvlen > length $pv;
833              
834 5 100       19 if( $pv =~ m/^[\x20-\x7e]*$/ ) {
835 3         19 $pv =~ s/(['\\])/\\$1/g;
836 3         7 $pv = qq('$pv');
837             }
838             else {
839 2 50       10 $pv =~ s{(\") | (\r) | (\n) | ([\x00-\x1f\x80-\xff])}
  2 50       26  
    50          
840 2         6 {$1?'\\"' : $2?"\\r" : $3?"\\n" : sprintf "\\x%02x", ord $4}egx;
841             $pv = qq("$pv");
842 5 100       13 }
843             $pv .= "..." if $truncated;
844 5         32  
845             return $pv;
846             }
847              
848             =head2 ourstash
849              
850             $stash = $sv->ourstash
851              
852             Returns the stash of the SCALAR, if it is an 'C' variable.
853              
854             After perl 5.20 this is no longer used, and will return C.
855              
856             =cut
857 102146     102146   103904  
  102146         367400  
858             sub ourstash { my $self = shift; return $self->df->sv_at( $self->ourstash_at ) }
859              
860             sub symname
861 2     2   5 {
862 2 100       32 my $self = shift;
863 1         7 return unless my $glob_at = $self->glob_at;
864             return $mksymname->( '$', $self->df->sv_at( $glob_at ) );
865             }
866              
867             sub type
868 440003     440003   472177 {
869 440003 100 100     2555265 my $self = shift;
      100        
      100        
870 196750         477519 return "SCALAR" if defined $self->uv or defined $self->iv or defined $self->nv or defined $self->pv;
871             return "UNDEF";
872             }
873              
874             sub desc
875 102059     102059   393274 {
876             my $self = shift;
877 102059         102871  
878 102059 100       213365 my @flags;
879 102059 100       165942 push @flags, "UV" if defined $self->uv;
880 102059 100       154507 push @flags, "IV" if defined $self->iv;
881 102059 100       185977 push @flags, "NV" if defined $self->nv;
882 102059         117312 push @flags, "PV" if defined $self->pv;
883 102059 100       159418 local $" = ",";
884 58391         137220 return "UNDEF()" unless @flags;
885             return "SCALAR(@flags)";
886             }
887              
888             sub _outrefs
889 102146     102146   104687 {
890 102146         123425 my $self = shift;
891             my ( $match, $no_desc ) = @_;
892 102146         103536  
893             my @outrefs;
894 102146 50 33     191666  
895 0 0       0 if( $match & STRENGTH_STRONG and my $ourstash = $self->ourstash ) {
896             push @outrefs, $no_desc ? ( strong => $ourstash ) :
897             Devel::MAT::SV::Reference( "the our stash", strong => $ourstash );
898             }
899 102146         145797  
900             return @outrefs;
901             }
902              
903 9     9   64 package Devel::MAT::SV::REF 0.49;
  9         12  
  9         845  
904             use base qw( Devel::MAT::SV );
905 9     9   52 __PACKAGE__->register_type( 3 );
  9         17  
  9         647  
906 9     9   44 use constant $CONSTANTS;
  9         59  
  9         3508  
907             use constant basetype => "SV";
908              
909             =head1 Devel::MAT::SV::REF
910              
911             Represents a referential scalar; any SCALAR-type SV with the C flag
912             set.
913              
914             =cut
915              
916             sub load
917 25310     25310   32318 {
918 25310         35838 my $self = shift;
919             my ( $header, $ptrs, $strs ) = @_;
920 25310         36769  
921             ( my $flags ) =
922             unpack "C", $header;
923              
924 25310         31983 $self->_set_ref_fields(
  25310         66434  
925             @{$ptrs}[0,1], # RV, OURSTASH
926             $flags & 0x01, # RV_IS_WEAK
927             );
928 25310         33011  
929 25310 50       48988 $flags &= ~0x01;
930             $flags and die sprintf "Unrecognised REF flags %02x\n", $flags;
931             }
932              
933             =head2 rv
934              
935             $svrv = $sv->rv
936              
937             Returns the SV referred to by the reference.
938              
939             =cut
940 18263     18263   21651  
  18263         54618  
941             sub rv { my $self = shift; return $self->df->sv_at( $self->rv_at ) }
942              
943             =head2 is_weak
944              
945             $weak = $sv->is_weak
946              
947             Returns true if the SV is a weakened RV reference.
948              
949             =cut
950              
951             # XS accessor
952              
953             =head2 ourstash
954              
955             $stash = $sv->ourstash
956              
957             Returns the stash of the SCALAR, if it is an 'C' variable.
958              
959             =cut
960 7258     7258   9976  
  7258         21118  
961             sub ourstash { my $self = shift; return $self->df->sv_at( $self->ourstash_at ) }
962              
963             sub desc
964 7230     7230   29725 {
965             my $self = shift;
966 7230 100       26262  
967             return sprintf "REF(%s)", $self->is_weak ? "W" : "";
968             }
969              
970             *symname = \&Devel::MAT::SV::SCALAR::symname;
971              
972             sub _outrefs
973 7258     7258   10231 {
974 7258         11553 my $self = shift;
975             my ( $match, $no_desc ) = @_;
976 7258         8129  
977             my @outrefs;
978 7258         22568  
979 7258 100 33     25170 my $is_weak = $self->is_weak;
    50          
980 7258 100       14588 if( $match & ( $is_weak ? STRENGTH_WEAK : STRENGTH_STRONG ) and my $rv = $self->rv ) {
981 7258 100       15185 my $strength = $is_weak ? "weak" : "strong";
982             push @outrefs, $no_desc ? ( $strength => $rv ) :
983             Devel::MAT::SV::Reference( "the referrant", $strength => $rv );
984             }
985 7258 50 33     20240  
986 0 0       0 if( $match & STRENGTH_STRONG and my $ourstash = $self->ourstash ) {
987             push @outrefs, $no_desc ? ( strong => $ourstash ) :
988             Devel::MAT::SV::Reference( "the our stash", strong => $ourstash );
989             }
990 7258         16179  
991             return @outrefs;
992             }
993              
994 9     9   52 package Devel::MAT::SV::BOOL 0.49;
  9         13  
  9         3158  
995             use base qw( Devel::MAT::SV::SCALAR );
996 0     0   0  
997             sub type { return "BOOL" }
998              
999             sub desc
1000 0     0   0 {
1001 0 0       0 my $self = shift;
1002 0         0 return "BOOL(YES)" if $self->uv;
1003             return "BOOL(NO)";
1004             }
1005              
1006 9     9   55 package Devel::MAT::SV::ARRAY 0.49;
  9         25  
  9         1023  
1007             use base qw( Devel::MAT::SV );
1008 9     9   52 __PACKAGE__->register_type( 4 );
  9         14  
  9         722  
1009 9     9   48 use constant $CONSTANTS;
  9         13  
  9         6719  
1010             use constant basetype => "AV";
1011              
1012             =head1 Devel::MAT::SV::ARRAY
1013              
1014             Represents an array; an SV of type C.
1015              
1016             =cut
1017              
1018             sub refcount_adjusted
1019 0     0   0 {
1020             my $self = shift;
1021 0 0       0 # AVs that are backrefs lists have an SvREFCNT artificially high
1022             return $self->refcnt - ( $self->is_backrefs ? 1 : 0 );
1023             }
1024              
1025             sub load
1026 51096     51096   66274 {
1027 51096         72367 my $self = shift;
1028 51096         89796 my ( $header, $ptrs, $strs ) = @_;
1029             my $df = $self->df;
1030 51096         119202  
1031             my ( $n, $flags ) =
1032             unpack "$df->{uint_fmt} C", $header;
1033 51096 100 100     185533  
1034             $self->_set_array_fields( $flags || 0, [ $n ? $df->_read_ptrs($n) : () ] );
1035             }
1036              
1037             sub _more_saved
1038 1     1   2 {
1039 1         3 my $self = shift;
1040             my ( $index, $addr ) = @_;
1041 1         2  
  1         7  
1042             push @{ $self->{saved} }, [ $index => $addr ];
1043             }
1044              
1045             =head2 is_unreal
1046              
1047             $unreal = $av->is_unreal
1048              
1049             Returns true if the C flag is not set on the array - i.e. that its
1050             SV pointers do not contribute to the C of the SVs it points at.
1051              
1052             =head2 is_backrefs
1053              
1054             $backrefs = $av->is_backrefs
1055              
1056             Returns true if the array contains the backrefs list of a hash or
1057             weakly-referenced object.
1058              
1059             =cut
1060              
1061             # XS accessors
1062              
1063             sub symname
1064 4     4   9 {
1065 4 100       37 my $self = shift;
1066 1         10 return unless my $glob_at = $self->glob_at;
1067             return $mksymname->( '@', $self->df->sv_at( $glob_at ) );
1068             }
1069              
1070             =head2 elems
1071              
1072             @svs = $av->elems
1073              
1074             Returns all of the element SVs in a list
1075              
1076             =cut
1077              
1078             sub elems
1079 20463     20463   27713 {
1080             my $self = shift;
1081 20463         41392  
1082 20463 100       46738 my $n = $self->n_elems;
1083             return $n unless wantarray;
1084 12073         25725  
1085 12073         133163 my $df = $self->df;
  5381551         8687278  
1086             return map { $df->sv_at( $self->elem_at( $_ ) ) } 0 .. $n-1;
1087             }
1088              
1089             =head2 elem
1090              
1091             $sv = $av->elem( $index )
1092              
1093             Returns the SV at the given index
1094              
1095             =cut
1096              
1097             sub elem
1098 4397232     4397232   4498905 {
1099 4397232         9354748 my $self = shift;
1100             return $self->df->sv_at( $self->elem_at( $_[0] ) );
1101             }
1102              
1103             sub desc
1104 8571     8571   35588 {
1105             my $self = shift;
1106 8571         19325  
1107             my @flags = $self->n_elems;
1108 8571 100       18345  
1109             push @flags, "!REAL" if $self->is_unreal;
1110 8571         9657  
1111 8571         19990 $" = ",";
1112             return "ARRAY(@flags)";
1113             }
1114              
1115             sub _outrefs
1116 12008     12008   15665 {
1117 12008         20699 my $self = shift;
1118             my ( $match, $no_desc ) = @_;
1119 12008         33506  
1120             my $n = $self->n_elems;
1121 12008         14937  
1122             my @outrefs;
1123 12008 100       32599  
1124 9786 50       20637 if( $self->is_unreal ) {
1125 9786         25472 if( $match & STRENGTH_WEAK ) {
1126 4349391 50       20342700 foreach my $idx ( 0 .. $n-1 ) {
1127             my $sv = $self->elem( $idx ) or next;
1128 4349391 100       8753982  
1129             push @outrefs, $no_desc ? ( weak => $sv ) :
1130             Devel::MAT::SV::Reference( "element " . Devel::MAT::Cmd->format_value( $idx, index => 1 ), weak => $sv );
1131             }
1132             }
1133             }
1134 2222         6123 else {
1135 22471 100       35671 foreach my $idx ( 0 .. $n-1 ) {
1136             my $sv = $self->elem( $idx ) or next;
1137 22379 100       37293  
1138             my $name = $no_desc ? undef :
1139 22379 100       34583 "element " . Devel::MAT::Cmd->format_value( $idx, index => 1 );
1140 22378 100       37367 if( $match & STRENGTH_STRONG ) {
1141             push @outrefs, $no_desc ? ( strong => $sv ) :
1142             Devel::MAT::SV::Reference( $name, strong => $sv );
1143 22379 50 100     90812 }
      66        
      66        
1144 2976 100       7416 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1145             push @outrefs, $no_desc ? ( indirect => $rv ) :
1146             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1147             }
1148             }
1149             }
1150 12008         31627  
  12008         41817  
1151 1         7 foreach my $saved ( @{ $self->{saved} } ) {
1152             my $sv = $self->df->sv_at( $saved->[1] );
1153 1 50       6  
1154             push @outrefs, $no_desc ? ( inferred => $sv ) :
1155             Devel::MAT::SV::Reference( "saved value of element " . Devel::MAT::Cmd->format_value( $saved->[0], index => 1 ),
1156             inferred => $sv );
1157             }
1158 12008         470596  
1159             return @outrefs;
1160             }
1161              
1162             package Devel::MAT::SV::PADLIST 0.49;
1163 9     9   56 # Synthetic type
  9         21  
  9         2442  
1164 9     9   53 use base qw( Devel::MAT::SV::ARRAY );
  9         15  
  9         364  
1165 9     9   40 use constant type => "PADLIST";
  9         14  
  9         2852  
1166             use constant $CONSTANTS;
1167              
1168             =head1 Devel::MAT::SV::PADLIST
1169              
1170             A subclass of ARRAY, this is used to represent the PADLIST of a CODE SV.
1171              
1172             =cut
1173 0     0   0  
  0         0  
1174             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1175              
1176             sub desc
1177 0     0   0 {
1178 0         0 my $self = shift;
1179             return "PADLIST(" . $self->n_elems . ")";
1180             }
1181              
1182             # Totally different outrefs format than ARRAY
1183             sub _outrefs
1184 0     0   0 {
1185 0         0 my $self = shift;
1186             my ( $match, $no_desc ) = @_;
1187 0         0  
1188             my @outrefs;
1189 0 0       0  
1190 0         0 if( $match & STRENGTH_STRONG ) {
1191 0         0 my $df = $self->df;
1192             my $n = $self->n_elems;
1193 0 0       0  
1194 0 0       0 if( my $padnames = $df->sv_at( $self->elem_at( 0 ) ) ) {
1195             push @outrefs, $no_desc ? ( strong => $padnames ) :
1196             Devel::MAT::SV::Reference( "the padnames", strong => $padnames );
1197             }
1198 0         0  
1199 0 0       0 foreach my $idx ( 1 .. $n-1 ) {
1200             my $pad = $df->sv_at( $self->elem_at( $idx ) ) or next;
1201 0 0       0  
1202             push @outrefs, $no_desc ? ( strong => $pad ) :
1203             Devel::MAT::SV::Reference( "pad at depth $idx", strong => $pad );
1204             }
1205             }
1206 0         0  
1207             return @outrefs;
1208             }
1209              
1210             package Devel::MAT::SV::PADNAMES 0.49;
1211 9     9   53 # Synthetic type
  9         17  
  9         2133  
1212 9     9   53 use base qw( Devel::MAT::SV::ARRAY );
  9         18  
  9         411  
1213 9     9   45 use constant type => "PADNAMES";
  9         16  
  9         3651  
1214             use constant $CONSTANTS;
1215              
1216             =head1 Devel::MAT::SV::PADNAMES
1217              
1218             A subclass of ARRAY, this is used to represent the PADNAMES of a CODE SV.
1219              
1220             =cut
1221 0     0   0  
  0         0  
1222             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1223              
1224             =head2 padname
1225              
1226             $padname = $padnames->padname( $padix )
1227              
1228             Returns the name of the lexical at the given index, or C
1229              
1230             =cut
1231              
1232             sub padname
1233 0     0   0 {
1234 0         0 my $self = shift;
1235 0 0       0 my ( $padix ) = @_;
1236 0 0       0 my $namepv = $self->elem( $padix ) or return undef;
1237 0         0 $namepv->type eq "SCALAR" or return undef;
1238             return $namepv->pv;
1239             }
1240              
1241             =head2 padix_from_padname
1242              
1243             $padix = $padnames->padix_from_padname( $padname )
1244              
1245             Returns the index of the lexical with the given name, or C
1246              
1247             =cut
1248              
1249             sub padix_from_padname
1250 0     0   0 {
1251 0         0 my $self = shift;
1252             my ( $padname ) = @_;
1253 0         0  
1254 0         0 foreach my $padix ( 1 .. scalar( $self->elems ) - 1 ) {
1255 0 0 0     0 my $namepv;
      0        
1256             return $padix if $namepv = $self->elem( $padix ) and
1257             $namepv->type eq "SCALAR" and
1258             $namepv->pv eq $padname;
1259             }
1260 0         0  
1261             return undef;
1262             }
1263              
1264             sub desc
1265 0     0   0 {
1266 0         0 my $self = shift;
1267             return "PADNAMES(" . scalar($self->elems) . ")";
1268             }
1269              
1270             # Totally different outrefs format than ARRAY
1271             sub _outrefs
1272 0     0   0 {
1273 0         0 my $self = shift;
1274             my ( $match, $no_desc ) = @_;
1275 0         0  
1276             my @outrefs;
1277 0 0       0  
1278 0         0 if( $match & STRENGTH_STRONG ) {
1279 0         0 my $df = $self->df;
1280             my $n = $self->n_elems;
1281 0         0  
1282 0 0       0 foreach my $idx ( 1 .. $n-1 ) {
1283             my $padname = $df->sv_at( $self->elem_at( $idx ) ) or next;
1284 0 0       0  
1285             push @outrefs, $no_desc ? ( strong => $padname ) :
1286             Devel::MAT::SV::Reference( "padname " . Devel::MAT::Cmd->format_value( $idx, index => 1 ), strong => $padname );
1287             }
1288             }
1289 0         0  
1290             return @outrefs;
1291             }
1292              
1293             package Devel::MAT::SV::PAD 0.49;
1294 9     9   54 # Synthetic type
  9         16  
  9         2133  
1295 9     9   52 use base qw( Devel::MAT::SV::ARRAY );
  9         14  
  9         346  
1296 9     9   40 use constant type => "PAD";
  9         14  
  9         5177  
1297             use constant $CONSTANTS;
1298              
1299             =head1 Devel::MAT::SV::PAD
1300              
1301             A subclass of ARRAY, this is used to represent a PAD of a CODE SV.
1302              
1303             =cut
1304              
1305             sub desc
1306 6025     6025   26048 {
1307 6025         9162 my $self = shift;
1308             return "PAD(" . scalar($self->elems) . ")";
1309             }
1310              
1311             =head2 padcv
1312              
1313             $cv = $pad->padcv
1314              
1315             Returns the C SV for which this is a pad.
1316              
1317             =cut
1318 6054     6054   8585  
  6054         27383  
1319             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1320              
1321             =head2 lexvars
1322              
1323             ( $name, $sv, $name, $sv, ... ) = $pad->lexvars
1324              
1325             Returns a name/value list of the lexical variables in the pad.
1326              
1327             =cut
1328              
1329             sub lexvars
1330 0     0   0 {
1331 0         0 my $self = shift;
1332             my $padcv = $self->padcv;
1333 0         0  
1334             my @svs = $self->elems;
1335 0         0 return map {
  0         0  
1336 0 0       0 my $padname = $padcv->padname( $_ );
1337             $padname ? ( $padname->name => $svs[$_] ) : ()
1338             } 1 .. $#svs;
1339             }
1340              
1341             =head2 maybe_lexvar
1342              
1343             $sv = $pad->maybe_lexvar( $padname )
1344              
1345             I
1346              
1347             Returns the SV associated with the given padname if one exists, or C if
1348             not.
1349              
1350             Used to be named C.
1351              
1352             =cut
1353              
1354             sub maybe_lexvar
1355 4     4   8 {
1356 4         9 my $self = shift;
1357             my ( $padname ) = @_;
1358 4 50       11  
1359 4         57 my $padix = $self->padcv->padix_from_padname( $padname ) or return undef;
1360             return $self->elem( $padix );
1361             }
1362              
1363             *lexvar = \&maybe_lexvar;
1364              
1365             # Totally different outrefs format than ARRAY
1366             sub _outrefs
1367 6048     6048   7843 {
1368 6048         9309 my $self = shift;
1369             my ( $match, $no_desc ) = @_;
1370 6048         13196  
1371             my $padcv = $self->padcv;
1372 6048         14191  
1373             my @svs = $self->elems;
1374 6048         10755  
1375             my @outrefs;
1376 6048 100 66     23703  
1377 5585 100       13931 if( $match & STRENGTH_STRONG and my $argsav = $svs[0] ) {
1378             push @outrefs, $no_desc ? ( strong => $argsav ) :
1379             Devel::MAT::SV::Reference( "the " . Devel::MAT::Cmd->format_note( '@_', 1 ) . " av", strong => $argsav );
1380             }
1381 6048         15581  
1382 49298 100       81155 foreach my $idx ( 1 .. $#svs ) {
1383             my $sv = $svs[$idx] or next;
1384 46593         46799  
1385 46593 100       61240 my $name;
1386 240         351 if( !$no_desc ) {
1387 240 100       522 my $padname = $padcv->padname( $idx );
1388 240 100       820 $name = $padname ? $padname->name : undef;
1389 70         138 if( $name ) {
1390             $name = "the lexical " . Devel::MAT::Cmd->format_note( $name, 1 );
1391             }
1392 170         243 else {
1393             $name = "pad temporary $idx";
1394             }
1395             }
1396 46593 50       62546  
1397 46593 100       67500 if( $match & STRENGTH_STRONG ) {
1398             push @outrefs, $no_desc ? ( strong => $sv ) :
1399             Devel::MAT::SV::Reference( $name, strong => $sv );
1400 46593 50 66     87406 }
      66        
      66        
1401 347 100       1097 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1402             push @outrefs, $no_desc ? ( indirect => $rv ) :
1403             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1404             }
1405             }
1406 6048         26253  
1407             return @outrefs;
1408             }
1409              
1410 9     9   54 package Devel::MAT::SV::HASH 0.49;
  9         55  
  9         769  
1411             use base qw( Devel::MAT::SV );
1412 9     9   49 __PACKAGE__->register_type( 5 );
  9         23  
  9         620  
1413 9     9   45 use constant $CONSTANTS;
  9         15  
  9         7997  
1414             use constant basetype => "HV";
1415              
1416             =head1 Devel::MAT::SV::HASH
1417              
1418             Represents a hash; an SV of type C. The C
1419             subclass is used to represent hashes that are used as stashes.
1420              
1421             =cut
1422              
1423             sub load
1424 9528     9528   15426 {
1425 9528         14227 my $self = shift;
1426 9528         18113 my ( $header, $ptrs, $strs ) = @_;
1427             my $df = $self->df;
1428 9528         24835  
1429             ( my $n ) =
1430             unpack "$df->{uint_fmt} a*", $header;
1431 9528         14990  
1432 9528         24885 my %values_at;
1433 161962         243292 foreach ( 1 .. $n ) {
1434 161962         245686 my $key = $df->_read_str;
1435             $values_at{$key} = $df->_read_ptr;
1436             }
1437              
1438 9528         202765 $self->_set_hash_fields(
1439             $ptrs->[0], # BACKREFS
1440             \%values_at,
1441             );
1442              
1443             }
1444              
1445             # Back-compat. for loading old .pmat files that didn't store AvREAL
1446             sub _fixup
1447 9528     9528   11330 {
1448             my $self = shift;
1449 9528 100       14558  
1450 2159 100       9676 if( my $backrefs = $self->backrefs ) {
1451             $backrefs->_set_backrefs( 1 ) if $backrefs->type eq "ARRAY";
1452             }
1453             }
1454              
1455             sub _more_saved
1456 1     1   4 {
1457 1         3 my $self = shift;
1458             my ( $keyaddr, $valaddr ) = @_;
1459 1         3  
  1         6  
1460             push @{ $self->{saved} }, [ $keyaddr, $valaddr ];
1461             }
1462              
1463             sub symname
1464 3     3   7 {
1465 3 50       32 my $self = shift;
1466 3         17 return unless my $glob_at = $self->glob_at;
1467             return $mksymname->( '%', $self->df->sv_at( $glob_at ) );
1468             }
1469              
1470             # HVs have a backrefs field directly, rather than using magic
1471             sub backrefs
1472 23307     23307   29000 {
1473 23307         76238 my $self = shift;
1474             return $self->df->sv_at( $self->backrefs_at );
1475             }
1476              
1477             =head2 keys
1478              
1479             @keys = $hv->keys
1480              
1481             Returns the set of keys present in the hash, as plain perl strings, in no
1482             particular order.
1483              
1484             =cut
1485              
1486             # XS accessor
1487              
1488             =head2 value
1489              
1490             $sv = $hv->value( $key )
1491              
1492             Returns the SV associated with the given key
1493              
1494             =cut
1495              
1496             sub value
1497 7371     7371   9379 {
1498 7371         10162 my $self = shift;
1499 7371         21409 my ( $key ) = @_;
1500             return $self->df->sv_at( $self->value_at( $key ) );
1501             }
1502              
1503             =head2 values
1504              
1505             @svs = $hv->values
1506              
1507             Returns all of the SVs stored as values, in no particular order (though, in an
1508             order corresponding to the order returned by C).
1509              
1510             =cut
1511              
1512             sub values
1513 517     517   555 {
1514 517 50       716 my $self = shift;
1515             return $self->n_values if !wantarray;
1516 517         1184  
1517 517         1351 my $df = $self->df;
  3696         5120  
1518             return map { $df->sv_at( $_ ) } $self->values_at;
1519             }
1520              
1521             sub desc
1522 2722     2722   11265 {
1523 2722 100       7702 my $self = shift;
1524 2722         8273 my $named = $self->{name} ? " named $self->{name}" : "";
1525             return "HASH(" . $self->n_values . ")";
1526             }
1527              
1528             sub _outrefs
1529 7817     7817   12554 {
1530 7817         13057 my $self = shift;
1531             my ( $match, $no_desc ) = @_;
1532 7817         26156  
1533             my $df = $self->df;
1534 7817         10986  
1535             my @outrefs;
1536 7817 100       24430  
1537             if( my $backrefs = $self->backrefs ) {
1538             # backrefs are optimised so if there's only one backref, it is stored
1539 5654 100       25102 # in the backrefs slot directly
1540 5644 50       15446 if( $backrefs->type eq "ARRAY" ) {
1541 5644 100       17286 if( $match & STRENGTH_STRONG ) {
1542             push @outrefs, $no_desc ? ( strong => $backrefs ) :
1543             Devel::MAT::SV::Reference( "the backrefs list", strong => $backrefs );
1544             }
1545 5644 50       34436  
1546 5644         10971 if( $match & STRENGTH_INDIRECT ) {
1547 5322674 100       21912092 foreach my $sv ( $self->backrefs->elems ) {
1548             push @outrefs, $no_desc ? ( indirect => $sv ) :
1549             Devel::MAT::SV::Reference( "a backref", indirect => $sv );
1550             }
1551             }
1552             }
1553 10 50       44 else {
1554 10 50       61 if( $match & STRENGTH_WEAK ) {
1555             push @outrefs, $no_desc ? ( weak => $backrefs ) :
1556             Devel::MAT::SV::Reference( "a backref", weak => $backrefs );
1557             }
1558             }
1559             }
1560 7817         938336  
1561 2266883 100       7769401 foreach my $key ( $self->keys ) {
1562 2243644 100       4469086 my $sv = $df->sv_at( $self->value_at( $key ) ) or next;
1563             my $name = $no_desc ? undef :
1564             "value " . Devel::MAT::Cmd->format_value( $key, key => 1 );
1565 2243644 50       3789392  
1566 2243644 100       3906799 if( $match & STRENGTH_STRONG ) {
1567             push @outrefs, $no_desc ? ( strong => $sv ) :
1568             Devel::MAT::SV::Reference( $name, strong => $sv );
1569 2243644 50 66     13887755 }
      66        
      66        
1570 4446 100       10810 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1571             push @outrefs, $no_desc ? ( indirect => $sv ) :
1572             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1573             }
1574             }
1575 7817         285067  
  7817         30857  
1576 1         7 foreach my $saved ( @{ $self->{saved} } ) {
1577 1         8 my $keysv = $self->df->sv_at( $saved->[0] );
1578             my $valsv = $self->df->sv_at( $saved->[1] );
1579 1 50       6  
1580             push @outrefs, $no_desc ? ( inferred => $keysv ) :
1581             Devel::MAT::SV::Reference( "a key for saved value",
1582 1 50       23 inferred => $keysv );
1583             push @outrefs, $no_desc ? ( inferred => $valsv ) :
1584             Devel::MAT::SV::Reference( "saved value of value " . Devel::MAT::Cmd->format_value( $keysv->pv, key => 1 ),
1585             inferred => $valsv );
1586             }
1587 7817         629958  
1588             return @outrefs;
1589             }
1590              
1591 9     9   58 package Devel::MAT::SV::STASH 0.49;
  9         37  
  9         2606  
1592             use base qw( Devel::MAT::SV::HASH );
1593 9     9   56 __PACKAGE__->register_type( 6 );
  9         13  
  9         5900  
1594             use constant $CONSTANTS;
1595              
1596             =head1 Devel::MAT::SV::STASH
1597              
1598             Represents a hash used as a stash; an SV of type C whose C
1599             is non-NULL. This is a subclass of C.
1600              
1601             =cut
1602              
1603             sub load
1604 2222     2222   3617 {
1605 2222         4798 my $self = shift;
1606 2222         4910 my ( $header, $ptrs, $strs ) = @_;
1607             my $df = $self->df;
1608 2222         2913  
  2222         4903  
1609             my ( $hash_bytes, $hash_ptrs, $hash_strs ) = @{ $df->{sv_sizes}[5] };
1610 2222         15020  
1611             $self->SUPER::load(
1612             substr( $header, 0, $hash_bytes, "" ),
1613             [ splice @$ptrs, 0, $hash_ptrs ],
1614             [ splice @$strs, 0, $hash_strs ],
1615             );
1616 2222         12375  
  2222         9752  
1617             @{$self}{qw( mro_linearall_at mro_linearcurrent_at mro_nextmethod_at mro_isa_at )} =
1618             @$ptrs;
1619 2222         8288  
1620             ( $self->{name} ) =
1621             @$strs;
1622             }
1623              
1624             =head2 mro_linear_all
1625              
1626             =head2 mro_linearcurrent
1627              
1628             =head2 mro_nextmethod
1629              
1630             =head2 mro_isa
1631              
1632             $hv = $stash->mro_linear_all
1633              
1634             $sv = $stash->mro_linearcurrent
1635              
1636             $sv = $stash->mro_nextmethod
1637              
1638             $av = $stash->mro_isa
1639              
1640             Returns the fields from the MRO structure
1641              
1642             =cut
1643 5989     5989   9247  
  5989         35870  
1644 5989     5989   9393 sub mro_linearall { my $self = shift; return $self->df->sv_at( $self->{mro_linearall_at} ) }
  5989         17698  
1645 5989     5989   8135 sub mro_linearcurrent { my $self = shift; return $self->df->sv_at( $self->{mro_linearcurrent_at} ) }
  5989         18586  
1646 5989     5989   7581 sub mro_nextmethod { my $self = shift; return $self->df->sv_at( $self->{mro_nextmethod_at} ) }
  5989         14889  
1647             sub mro_isa { my $self = shift; return $self->df->sv_at( $self->{mro_isa_at} ) }
1648              
1649             =head2 value_code
1650              
1651             $cv = $stash->value_code( $key )
1652              
1653             Returns the CODE associated with the given symbol name, if it exists, or
1654             C if not. This is roughly equivalent to
1655              
1656             $cv = $stash->value( $key )->code
1657              
1658             Except that it is aware of the direct reference to CVs that perl 5.22 will
1659             optimise for. This method should be used in preference to the above construct.
1660              
1661             =cut
1662              
1663             sub value_code
1664 1     1   245 {
1665 1         5 my $self = shift;
1666             my ( $key ) = @_;
1667 1 50       5  
1668 1 50       10 my $sv = $self->value( $key ) or return undef;
    0          
1669 1         5 if( $sv->type eq "GLOB" ) {
1670             return $sv->code;
1671             }
1672 0         0 elsif( $sv->type eq "REF" ) {
1673             return $sv->rv;
1674             }
1675 0         0  
  0         0  
1676             die "TODO: value_code on non-GLOB, non-REF ${\ $sv->desc }";
1677             }
1678              
1679             =head2 stashname
1680              
1681             $name = $stash->stashname
1682              
1683             Returns the name of the stash
1684              
1685             =cut
1686              
1687             sub stashname
1688 28     28   46 {
1689 28         199 my $self = shift;
1690             return $self->{name};
1691             }
1692              
1693             sub desc
1694 635     635   3877 {
1695 635         1841 my $self = shift;
1696 635         4144 my $desc = $self->SUPER::desc;
1697 635         1443 $desc =~ s/^HASH/STASH/;
1698             return $desc;
1699             }
1700              
1701             sub _outrefs
1702 5672     5672   8694 {
1703 5672         11933 my $self = shift;
1704             my ( $match, $no_desc ) = @_;
1705 5672         22000  
1706             my @outrefs = $self->SUPER::_outrefs( @_ );
1707 5672 50       41279  
1708 5672 50       19615 if( $match & STRENGTH_STRONG ) {
1709 0 0       0 if( my $sv = $self->mro_linearall ) {
1710             push @outrefs, $no_desc ? ( strong => $sv ) :
1711             Devel::MAT::SV::Reference( "the mro linear all HV", strong => $sv );
1712 5672 100       14110 }
1713 1926 100       8161 if( my $sv = $self->mro_linearcurrent ) {
1714             push @outrefs, $no_desc ? ( strong => $sv ) :
1715             Devel::MAT::SV::Reference( "the mro linear current", strong => $sv );
1716 5672 50       20742 }
1717 0 0       0 if( my $sv = $self->mro_nextmethod ) {
1718             push @outrefs, $no_desc ? ( strong => $sv ) :
1719             Devel::MAT::SV::Reference( "the mro next::method", strong => $sv );
1720 5672 100       13368 }
1721 1926 100       5682 if( my $sv = $self->mro_isa ) {
1722             push @outrefs, $no_desc ? ( strong => $sv ) :
1723             Devel::MAT::SV::Reference( "the mro ISA cache", strong => $sv );
1724             }
1725             }
1726 5672         332501  
1727             return @outrefs;
1728             }
1729              
1730 9     9   58 package Devel::MAT::SV::CODE 0.49;
  9         17  
  9         791  
1731             use base qw( Devel::MAT::SV );
1732 9     9   48 __PACKAGE__->register_type( 7 );
  9         21  
  9         798  
1733 9     9   54 use constant $CONSTANTS;
  9         16  
  9         424  
1734             use constant basetype => "CV";
1735 9     9   49  
  9         15  
  9         592  
1736             use Carp;
1737 9     9   52  
  9         165  
  9         536  
1738             use List::Util 1.44 qw( uniq );
1739 9     9   50  
  9         95  
  9         50  
1740             use Struct::Dumb 0.07 qw( struct );
1741             struct Padname => [qw( name ourstash flags fieldix fieldstash_at )];
1742 9     9   652 {
  9         13  
  9         23149  
1743 0     0   0 no strict 'refs';
1744 0     0   0 *{__PACKAGE__."::Padname::is_outer"} = sub { shift->flags & 0x01 };
1745 0     0   0 *{__PACKAGE__."::Padname::is_state"} = sub { shift->flags & 0x02 };
1746 0     0   0 *{__PACKAGE__."::Padname::is_lvalue"} = sub { shift->flags & 0x04 };
1747 0     0   0 *{__PACKAGE__."::Padname::is_typed"} = sub { shift->flags & 0x08 };
1748             *{__PACKAGE__."::Padname::is_our"} = sub { shift->flags & 0x10 };
1749              
1750 0     0   0 # Internal flags, not appearing in the file itself
1751             *{__PACKAGE__."::Padname::is_field"} = sub { shift->flags & 0x100 };
1752             }
1753              
1754             =head1 Devel::MAT::SV::CODE
1755              
1756             Represents a function or closure; an SV of type C.
1757              
1758             =cut
1759              
1760             sub load
1761 40432     40432   54251 {
1762 40432         59012 my $self = shift;
1763 40432         74027 my ( $header, $ptrs, $strs ) = @_;
1764             my $df = $self->df;
1765 40432         122179  
1766             my ( $line, $flags, $oproot, $depth ) =
1767             unpack "$df->{uint_fmt} C $df->{ptr_fmt} $df->{u32_fmt}", $header;
1768 40432 50       74927  
1769             defined $depth or $depth = -1;
1770              
1771 40432         55260 $self->_set_code_fields( $line, $flags, $oproot, $depth,
1772 40432         54756 @{$ptrs}[0, 2..4], # STASH, OUTSIDE, PADLIST, CONSTVAL
  40432         134045  
1773             @{$strs}[0, 1], # FILE, NAME
1774 40432         97252 );
1775             $self->_set_glob_at( $ptrs->[1] );
1776              
1777 40432 50       116075 # After perl 5.20 individual padname structs are no longer arena-allocated
1778             $self->{padnames} = [] if $df->{perlver} > ( ( 5 << 24 ) | ( 20 << 16 ) | 0xffff );
1779 40432         85570  
1780             while( my $type = $df->_read_u8 ) {
1781 109703         106374 match( $type : == ) {
  109703         189700  
1782 0         0 case( 1 ) { push @{ $self->{consts_at} }, $df->_read_ptr }
  0         0  
1783 41598         42072 case( 2 ) { push @{ $self->{constix} }, $df->_read_uint }
  41598         81624  
1784 0         0 case( 3 ) { push @{ $self->{gvs_at} }, $df->_read_ptr }
  0         0  
1785 164116         240871 case( 4 ) { push @{ $self->{gvix} }, $df->_read_uint }
1786 164116         211052 case( 5 ) { my $padix = $df->_read_uint;
1787             $self->{padnames}[$padix] = _load_padname( $df ); }
1788 0         0 case( 6 ) { # ignore - used to be padsvs_at
  0         0  
  0         0  
1789 21035         37226 $df->_read_uint; $df->_read_uint; $df->_read_ptr; }
1790 21105         35518 case( 7 ) { $self->_set_padnames_at( $df->_read_ptr ); }
1791 21105         37650 case( 8 ) { my $depth = $df->_read_uint;
1792 32037         59092 $self->{pads_at}[$depth] = $df->_read_ptr; }
1793 32037         54084 case( 9 ) { my $padname = $self->{padnames}[ $df->_read_uint ];
1794 0         0 $padname->flags = $df->_read_u8; }
1795 0         0 case( 10 ) { my $padname = $self->{padnames}[ $df->_read_uint ];
1796 0         0 $padname->flags |= 0x100;
1797 0         0 $padname->fieldix = $df->_read_uint;
1798 389594 100       782226 $padname->fieldstash_at = $df->_read_ptr; }
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    0          
1799 0         0 default {
1800             die "TODO: unhandled CODEx type $type";
1801             }
1802             }
1803             }
1804             }
1805              
1806             sub _load_padname
1807 164116     164116   193130 {
1808             my ( $df ) = @_;
1809 164116         237222  
1810             return Padname( $df->_read_str, $df->_read_ptr, 0, 0, 0 );
1811             }
1812              
1813             sub _fixup
1814 40432     40432   44570 {
1815             my $self = shift;
1816 40432         73840  
1817             my $df = $self->df;
1818 40432         49318  
1819 40432 50       58564 my $padlist = $self->padlist;
1820 0         0 if( $padlist ) {
1821 0         0 bless $padlist, "Devel::MAT::SV::PADLIST";
1822             $padlist->_set_padcv_at( $self->addr );
1823             }
1824 40432         43673  
1825             my $padnames;
1826             my @pads;
1827              
1828 40432 50       57377 # 5.18.0 onwards has a totally different padlist arrangement
    0          
1829 40432         52757 if( $df->{perlver} >= ( ( 5 << 24 ) | ( 18 << 16 ) ) ) {
1830             $padnames = $self->padnames_av;
1831 40432         45036  
  42140         60733  
  40432         98927  
1832 40432         49118 @pads = map { $df->sv_at( $_ ) } @{ $self->{pads_at} };
1833             shift @pads; # always zero
1834             }
1835             elsif( $padlist ) {
1836             # PADLIST[0] stores the names of the lexicals
1837 0         0 # The rest stores the actual pads
1838 0         0 ( $padnames, @pads ) = $padlist->elems;
1839             $self->_set_padnames_at( $padnames->addr );
1840             }
1841 40432 50       54174  
1842 0         0 if( $padnames ) {
1843 0         0 bless $padnames, "Devel::MAT::SV::PADNAMES";
1844             $padnames->_set_padcv_at( $self->addr );
1845 0         0  
1846             $self->{padnames} = \my @padnames;
1847 0         0  
1848 0 0       0 foreach my $padix ( 1 .. $padnames->elems - 1 ) {
1849 0 0       0 my $padnamesv = $padnames->elem( $padix ) or next;
1850             $padnamesv->immortal and next; # UNDEF
1851 0         0  
1852             $padnames[$padix] = Padname( $padnamesv->pv, $padnamesv->ourstash, 0, 0, 0 );
1853             }
1854             }
1855 40432         49591  
1856 21105 100       30992 foreach my $pad ( @pads ) {
1857             next unless $pad;
1858 21098         25861  
1859 21098         48830 bless $pad, "Devel::MAT::SV::PAD";
1860             $pad->_set_padcv_at( $self->addr );
1861             }
1862 40432         58830  
1863             $self->{pads} = \@pads;
1864              
1865 40432 50       65181 # Under ithreads, constants and captured GVs are actually stored in the first padlist
1866 0         0 if( $df->ithreads ) {
1867             my $pad0 = $pads[0];
1868 0         0  
1869 0 0       0 foreach my $type (qw( const gv )) {
1870 0   0     0 my $idxes = $self->{"${type}ix"} or next;
1871             my $svs_at = $self->{"${type}s_at"} ||= [];
1872 0         0  
  0         0  
1873 0 0       0 @$svs_at = map { my $e = $pad0->elem($_);
1874             $e ? $e->addr : undef } uniq @$idxes;
1875             }
1876             }
1877 40432 100 66     114078  
1878 2460 50       8299 if( $self->is_cloned and my $oproot = $self->oproot ) {
1879 2460         8123 if( my $protosub = $df->{protosubs_by_oproot}{$oproot} ) {
1880             $self->_set_protosub_at( $protosub->addr );
1881             }
1882             }
1883             }
1884              
1885             =head2 stash
1886              
1887             =head2 glob
1888              
1889             =head2 file
1890              
1891             =head2 line
1892              
1893             =head2 scope
1894              
1895             =head2 padlist
1896              
1897             =head2 constval
1898              
1899             =head2 oproot
1900              
1901             =head2 depth
1902              
1903             $stash = $cv->stash
1904              
1905             $gv = $cv->glob
1906              
1907             $filename = $cv->file
1908              
1909             $line = $cv->line
1910              
1911             $scope_cv = $cv->scope
1912              
1913             $av = $cv->padlist
1914              
1915             $sv = $cv->constval
1916              
1917             $addr = $cv->oproot
1918              
1919             $depth = $cv->depth
1920              
1921             Returns the stash, glob, filename, line number, scope, padlist, constant value,
1922             oproot or depth of the code.
1923              
1924             =cut
1925 14942     14942   19918  
  14942         45687  
1926 14965     14965   19154 sub stash { my $self = shift; return $self->df->sv_at( $self->stash_at ) }
  14965         42774  
1927             sub glob { my $self = shift; return $self->df->sv_at( $self->glob_at ) }
1928 20057     20057   24263 # XS accessors: file, line
  20057         51932  
1929 60489     60489   69223 sub scope { my $self = shift; return $self->df->sv_at( $self->outside_at ) }
  60489         168595  
1930 31608     31608   37788 sub padlist { my $self = shift; return $self->df->sv_at( $self->padlist_at ) }
  31608         87455  
1931             sub constval { my $self = shift; return $self->df->sv_at( $self->constval_at ) }
1932             # XS accessors: oproot, depth
1933              
1934             =head2 location
1935              
1936             $location = $cv->location
1937              
1938             Returns C if the line is defined, or C if not.
1939              
1940             =cut
1941              
1942             sub location
1943 0     0   0 {
1944 0         0 my $self = shift;
1945 0         0 my $line = $self->line;
1946             my $file = $self->file;
1947 0 0       0 # line 0 is invalid
1948             return $line ? "$file line $line" : $file;
1949             }
1950              
1951             =head2 is_clone
1952              
1953             =head2 is_cloned
1954              
1955             =head2 is_xsub
1956              
1957             =head2 is_weakoutside
1958              
1959             =head2 is_cvgv_rc
1960              
1961             =head2 is_lexical
1962              
1963             $clone = $cv->is_clone
1964              
1965             $cloned = $cv->is_cloned
1966              
1967             $xsub = $cv->is_xsub
1968              
1969             $weak = $cv->is_weakoutside
1970              
1971             $rc = $cv->is_cvgv_rc
1972              
1973             $lexical = $cv->is_lexical
1974              
1975             Returns the C, C, C, C,
1976             C and C flags.
1977              
1978             =cut
1979              
1980             # XS accessors
1981              
1982             =head2 protosub
1983              
1984             $protosub = $cv->protosub
1985              
1986             Returns the protosub CV, if known, for a closure CV.
1987              
1988             =cut
1989 14943     14943   18489  
  14943         42594  
1990             sub protosub { my $self = shift; return $self->df->sv_at( $self->protosub_at ); }
1991              
1992             =head2 constants
1993              
1994             @svs = $cv->constants
1995              
1996             Returns a list of the SVs used as constants or method names in the code. On
1997             ithreads perl the constants are part of the padlist structure so this list is
1998             constructed from parts of the padlist at loading time.
1999              
2000             =cut
2001              
2002             sub constants
2003 20058     20058   24297 {
2004 20058         30247 my $self = shift;
2005 20058 100       24663 my $df = $self->df;
  44762         65347  
  20058         76896  
2006             return map { $df->sv_at($_) } @{ $self->{consts_at} || [] };
2007             }
2008              
2009             =head2 globrefs
2010              
2011             @svs = $cv->globrefs
2012              
2013             Returns a list of the SVs used as GLOB references in the code. On ithreads
2014             perl the constants are part of the padlist structure so this list is
2015             constructed from parts of the padlist at loading time.
2016              
2017             =cut
2018              
2019             sub globrefs
2020 20057     20057   27071 {
2021 20057         34448 my $self = shift;
2022 20057         23870 my $df = $self->df;
  17577         28823  
  20057         63899  
2023             return map { $df->sv_at($_) } @{ $self->{gvs_at} };
2024             }
2025 0 0   0   0  
  0         0  
2026             sub stashname { my $self = shift; return $self->stash ? $self->stash->stashname : undef }
2027              
2028             sub symname
2029 23     23   33 {
2030             my $self = shift;
2031              
2032 23 50       79 # CvLEXICALs or CVs with non-reified CvGVs may still have a hekname
    100          
2033 0         0 if( defined( my $hekname = $self->hekname ) ) {
2034 0         0 my $stashname = $self->stashname;
2035 0         0 $stashname =~ s/^main:://;
2036             return '&' . $stashname . "::" . $hekname;
2037             }
2038 22         45 elsif( my $glob = $self->glob ) {
2039             return '&' . $glob->stashname;
2040             }
2041 1         4  
2042             return undef;
2043             }
2044              
2045             =head2 padname
2046              
2047             $padname = $cv->padname( $padix )
2048              
2049             Returns the name of the $padix'th lexical variable, or C if it doesn't
2050             have a name.
2051              
2052             The returned padname is a structure of the following fields:
2053              
2054             $name = $padname->name
2055              
2056             $bool = $padname->is_outer
2057             $bool = $padname->is_state
2058             $bool = $padname->is_lvalue
2059             $bool = $padname->is_typed
2060             $bool = $padname->is_our
2061             $bool = $padname->is_field
2062              
2063             =cut
2064              
2065             sub padname
2066 241     241   251 {
2067 241         302 my $self = shift;
2068             my ( $padix ) = @_;
2069 241         376  
2070             return $self->{padnames}[$padix];
2071             }
2072              
2073             =head2 padix_from_padname
2074              
2075             $padix = $cv->padix_from_padname( $padname )
2076              
2077             Returns the index of the first lexical variable with the given pad name, or
2078             C if one does not exist.
2079              
2080             =cut
2081              
2082             sub padix_from_padname
2083 5     5   484 {
2084 5         11 my $self = shift;
2085             my ( $padname ) = @_;
2086 5         11  
2087             my $padnames = $self->{padnames};
2088 5         18  
2089 29         84 foreach my $padix ( 1 .. $#$padnames ) {
2090             my $thisname;
2091 29 100 66     73  
      100        
2092             return $padix if defined $padnames->[$padix] and
2093             defined( $thisname = $padnames->[$padix]->name ) and
2094             $thisname eq $padname;
2095             }
2096 0         0  
2097             return undef;
2098             }
2099              
2100             =head2 max_padix
2101              
2102             $max_padix = $cv->max_padix
2103              
2104             Returns the maximum valid pad index.
2105              
2106             This is typically used to create a list of potential pad indexes, such as
2107              
2108             0 .. $cv->max_padix
2109              
2110             Note that since pad slots may contain things other than lexical variables, not
2111             every pad slot between 0 and this index will necessarily contain a lexical
2112             variable or have a pad name.
2113              
2114             =cut
2115              
2116             sub max_padix
2117 1     1   4 {
2118 1         3 my $self = shift;
  1         9  
2119             return $#{ $self->{padnames} };
2120             }
2121              
2122             =head2 padnames_av
2123              
2124             $padnames_av = $cv->padnames_av
2125              
2126             Returns the AV reference directly which stores the pad names.
2127              
2128             After perl version 5.20, this is no longer used directly and will return
2129             C. The individual pad names themselves can still be found via the
2130             C method.
2131              
2132             =cut
2133              
2134             sub padnames_av
2135 60489     60489   68062 {
2136             my $self = shift;
2137 60489   50     152273  
      0        
2138 0         0 return $self->df->sv_at( $self->padnames_at or return undef )
2139             // croak "${\ $self->desc } PADNAMES is not accessible";
2140             }
2141              
2142             =head2 pads
2143              
2144             @pads = $cv->pads
2145              
2146             Returns a list of the actual pad AVs.
2147              
2148             =cut
2149              
2150             sub pads
2151 5115     5115   5594 {
2152 5115 50       14011 my $self = shift;
  5115         11871  
2153             return $self->{pads} ? @{ $self->{pads} } : ();
2154             }
2155              
2156             =head2 pad
2157              
2158             $pad = $cv->pad( $depth )
2159              
2160             Returns the PAD at the given depth (given by 1-based index).
2161              
2162             =cut
2163              
2164             sub pad
2165 7     7   717 {
2166 7         18 my $self = shift;
2167 7 50       47 my ( $depth ) = @_;
2168             return $self->{pads} ? $self->{pads}[$depth-1] : undef;
2169             }
2170              
2171             =head2 maybe_lexvar
2172              
2173             $sv = $cv->maybe_lexvar( $padname, $depth )
2174              
2175             I
2176              
2177             Returns the SV on the PAD associated with the given padname, at the
2178             optionally-given depth (1-based index). If I<$depth> is not provided, the
2179             topmost live PAD will be used. If no variable exists of the given name returns
2180             C.
2181              
2182             Used to be called C.
2183              
2184             =cut
2185              
2186             sub maybe_lexvar
2187 3     3   7 {
2188 3         9 my $self = shift;
2189             my ( $padname, $depth ) = @_;
2190 3   66     20  
2191 3 50       13 $depth //= $self->depth;
2192             $depth or croak "Cannot fetch current pad of a non-live CODE";
2193 3         13  
2194             return $self->pad( $depth )->maybe_lexvar( $padname );
2195             }
2196              
2197             *lexvar = \&maybe_lexvar;
2198              
2199             sub desc
2200 11551     11551   47810 {
2201             my $self = shift;
2202 11551         12275  
2203 11551 100       28024 my @flags;
2204 11551 100       16674 push @flags, "PP" if $self->oproot;
2205 11551 100       22935 push @flags, "CONST" if $self->constval;
2206             push @flags, "XS" if $self->is_xsub;
2207 11551 100       19208  
2208 11551 100       17729 push @flags, "closure" if $self->is_cloned;
2209             push @flags, "proto" if $self->is_clone;
2210 11551         12958  
2211 11551         25282 local $" = ",";
2212             return "CODE(@flags)";
2213             }
2214              
2215             sub _outrefs
2216 14942     14942   19693 {
2217 14942         24825 my $self = shift;
2218             my ( $match, $no_desc ) = @_;
2219 14942         41303  
2220             my $pads = $self->{pads};
2221 14942 50       35442  
2222             my $maxdepth = $pads ? scalar @$pads : 0;
2223 14942         33828  
2224             my $have_padlist = defined $self->padlist;
2225 14942         21143  
2226             my @outrefs;
2227 14942         34538  
2228 14942 100 66     49286 my $is_weakoutside = $self->is_weakoutside;
    100          
2229 5792 100       12664 if( $match & ( $is_weakoutside ? STRENGTH_WEAK : STRENGTH_STRONG ) and my $scope = $self->scope ) {
2230 5792 100       13365 my $strength = $is_weakoutside ? "weak" : "strong";
2231             push @outrefs, $no_desc ? ( $strength => $scope ) :
2232             Devel::MAT::SV::Reference( "the scope", $strength => $scope );
2233             }
2234 14942 100 66     45324  
2235 12724 100       35569 if( $match & STRENGTH_WEAK and my $stash = $self->stash ) {
2236             push @outrefs, $no_desc ? ( weak => $stash ) :
2237             Devel::MAT::SV::Reference( "the stash", weak => $stash );
2238             }
2239 14942         43330  
2240 14942 100 66     45680 my $is_strong_gv = $self->is_cvgv_rc;
    100          
2241 14671 100       26148 if( $match & ( $is_strong_gv ? STRENGTH_STRONG : STRENGTH_WEAK ) and my $glob = $self->glob ) {
2242 14671 100       29802 my $strength = $is_strong_gv ? "strong" : "weak";
2243             push @outrefs, $no_desc ? ( $strength => $glob ) :
2244             Devel::MAT::SV::Reference( "the glob", $strength => $glob );
2245             }
2246 14942 100 66     51568  
2247 6674 100       18470 if( $match & STRENGTH_STRONG and my $constval = $self->constval ) {
2248             push @outrefs, $no_desc ? ( strong => $constval ) :
2249             Devel::MAT::SV::Reference( "the constant value", strong => $constval );
2250             }
2251 14942 100 66     49682  
2252 704 100       2080 if( $match & STRENGTH_INFERRED and my $protosub = $self->protosub ) {
2253             push @outrefs, $no_desc ? ( inferred => $protosub ) :
2254             Devel::MAT::SV::Reference( "the protosub", inferred => $protosub );
2255             }
2256              
2257             # Under ithreads, constants and captured GVs are actually stored in the
2258 14942         43291 # first padlist, so they're only here.
2259             my $ithreads = $self->df->ithreads;
2260 14942 50       37065  
    50          
2261 14942 50       23409 if( $match & ( $ithreads ? STRENGTH_INDIRECT : STRENGTH_STRONG ) ) {
2262             my $strength = $ithreads ? "indirect" : "strong";
2263 14942         26746  
2264 31563 50       48621 foreach my $sv ( $self->constants ) {
2265 31563 100       51735 $sv or next;
2266             push @outrefs, $no_desc ? ( $strength => $sv ) :
2267             Devel::MAT::SV::Reference( "a constant", $strength => $sv );
2268 14942         28743 }
2269 11973 50       20014 foreach my $sv ( $self->globrefs ) {
2270 11973 100       22331 $sv or next;
2271             push @outrefs, $no_desc ? ( $strength => $sv ) :
2272             Devel::MAT::SV::Reference( "a referenced glob", $strength => $sv );
2273             }
2274             }
2275 14942 50 33     47267  
2276 0 0       0 if( $match & STRENGTH_STRONG and $have_padlist ) {
2277             push @outrefs, $no_desc ? ( strong => $self->padlist ) :
2278             Devel::MAT::SV::Reference( "the padlist", strong => $self->padlist );
2279             }
2280              
2281             # If we have a PADLIST then its contents are indirect; if not then they
2282 14942 50       34741 # are direct strong
    50          
2283 14942 50       23148 if( $match & ( $have_padlist ? STRENGTH_INDIRECT : STRENGTH_STRONG ) ) {
2284             my $strength = $have_padlist ? "indirect" : "strong";
2285 14942 50       32362  
2286 0 0       0 if( my $padnames_av = $self->padnames_av ) {
2287             push @outrefs, $no_desc ? ( $strength => $padnames_av ) :
2288             Devel::MAT::SV::Reference( "the padnames", $strength => $padnames_av );
2289             }
2290 14942         34937  
2291 6079 100       19578 foreach my $depth ( 1 .. $maxdepth ) {
2292             my $pad = $pads->[$depth-1] or next;
2293 6077 100       15701  
2294             push @outrefs, $no_desc ? ( $strength => $pad ) :
2295             Devel::MAT::SV::Reference( "pad at depth $depth", $strength => $pad );
2296             }
2297             }
2298 14942         53253  
2299             return @outrefs;
2300             }
2301              
2302 9     9   92 package Devel::MAT::SV::IO 0.49;
  9         23  
  9         985  
2303             use base qw( Devel::MAT::SV );
2304 9     9   50 __PACKAGE__->register_type( 8 );
  9         12  
  9         757  
2305 9     9   67 use constant $CONSTANTS;
  9         33  
  9         4230  
2306             use constant basetype => "IO";
2307              
2308             =head1 Devel::MAT::SV::IO
2309              
2310             Represents an IO handle; an SV type of C.
2311              
2312             =cut
2313              
2314             sub load
2315 112     112   220 {
2316 112         244 my $self = shift;
2317 112         362 my ( $header, $ptrs, $strs ) = @_;
2318             my $df = $self->df;
2319 112         325  
  112         470  
2320             @{$self}{qw( ifileno ofileno )} =
2321             unpack "$df->{uint_fmt}2", $header;
2322              
2323 112   66     247 defined $_ and $_ == $df->{minus_1} and
  112   100     876  
2324             $_ = -1 for @{$self}{qw( ifileno ofileno )};
2325 112         1811  
  112         447  
2326             @{$self}{qw( topgv_at formatgv_at bottomgv_at )} =
2327             @$ptrs;
2328             }
2329              
2330             =head2 ifileno
2331              
2332             =head2 ofileno
2333              
2334             $ifileno = $io->ifileno
2335              
2336             $ofileno = $io->ofileno
2337              
2338             Returns the input or output file numbers.
2339              
2340             =cut
2341 0     0   0  
  0         0  
2342 1     1   7 sub ifileno { my $self = shift; return $self->{ifileno} }
  1         9  
2343             sub ofileno { my $self = shift; return $self->{ofileno} }
2344 32     32   71  
  32         189  
2345 32     32   56 sub topgv { my $self = shift; $self->df->sv_at( $self->{topgv_at} ) }
  32         125  
2346 32     32   52 sub formatgv { my $self = shift; $self->df->sv_at( $self->{formatgv_at} ) }
  32         126  
2347             sub bottomgv { my $self = shift; $self->df->sv_at( $self->{bottomgv_at} ) }
2348 32     32   286  
2349             sub desc { "IO()" }
2350              
2351             sub _outrefs
2352 32     32   57 {
2353 32         72 my $self = shift;
2354             my ( $match, $no_desc ) = @_;
2355 32         69  
2356             my @outrefs;
2357 32 50       126  
2358 32 50       145 if( $match & STRENGTH_STRONG ) {
2359 0 0       0 if( my $gv = $self->topgv ) {
2360             push @outrefs, $no_desc ? ( strong => $gv ) :
2361             Devel::MAT::SV::Reference( "the top GV", strong => $gv );
2362 32 50       117 }
2363 0 0       0 if( my $gv = $self->formatgv ) {
2364             push @outrefs, $no_desc ? ( strong => $gv ) :
2365             Devel::MAT::SV::Reference( "the format GV", strong => $gv );
2366 32 50       122 }
2367 0 0       0 if( my $gv = $self->bottomgv ) {
2368             push @outrefs, $no_desc ? ( strong => $gv ) :
2369             Devel::MAT::SV::Reference( "the bottom GV", strong => $gv );
2370             }
2371             }
2372 32         72  
2373             return @outrefs;
2374             }
2375              
2376 9     9   56 package Devel::MAT::SV::LVALUE 0.49;
  9         13  
  9         760  
2377             use base qw( Devel::MAT::SV );
2378 9     9   51 __PACKAGE__->register_type( 9 );
  9         19  
  9         651  
2379 9     9   56 use constant $CONSTANTS;
  9         16  
  9         3001  
2380             use constant basetype => "LV";
2381              
2382             sub load
2383 1     1   2 {
2384 1         2 my $self = shift;
2385 1         7 my ( $header, $ptrs, $strs ) = @_;
2386             my $df = $self->df;
2387 1         14  
2388             ( $self->{type}, $self->{off}, $self->{len} ) =
2389             unpack "a1 $df->{uint_fmt}2", $header;
2390 1         5  
2391             ( $self->{targ_at} ) =
2392             @$ptrs;
2393             }
2394 1     1   4  
  1         5  
2395 0     0   0 sub lvtype { my $self = shift; return $self->{type} }
  0         0  
2396 0     0   0 sub off { my $self = shift; return $self->{off} }
  0         0  
2397 0     0   0 sub len { my $self = shift; return $self->{len} }
  0         0  
2398             sub target { my $self = shift; return $self->df->sv_at( $self->{targ_at} ) }
2399 0     0   0  
2400             sub desc { "LVALUE()" }
2401              
2402             sub _outrefs
2403 0     0   0 {
2404 0         0 my $self = shift;
2405             my ( $match, $no_desc ) = @_;
2406 0         0  
2407             my @outrefs;
2408 0 0 0     0  
2409 0 0       0 if( $match & STRENGTH_STRONG and my $sv = $self->target ) {
2410             push @outrefs, $no_desc ? ( strong => $sv ) :
2411             Devel::MAT::SV::Reference( "the target", strong => $sv );
2412             }
2413 0         0  
2414             return @outrefs;
2415             }
2416              
2417 9     9   54 package Devel::MAT::SV::REGEXP 0.49;
  9         14  
  9         735  
2418 9     9   53 use base qw( Devel::MAT::SV );
  9         32  
  9         923  
2419             use constant basetype => "REGEXP";
2420             __PACKAGE__->register_type( 10 );
2421       4981      
2422             sub load {}
2423 1421     1421   7871  
2424             sub desc { "REGEXP()" }
2425 1424     1424   2214  
2426             sub _outrefs { () }
2427              
2428 9     9   50 package Devel::MAT::SV::FORMAT 0.49;
  9         16  
  9         785  
2429 9     9   51 use base qw( Devel::MAT::SV );
  9         12  
  9         930  
2430             use constant basetype => "PVFM";
2431             __PACKAGE__->register_type( 11 );
2432       0      
2433             sub load {}
2434 0     0   0  
2435             sub desc { "FORMAT()" }
2436 0     0   0  
2437             sub _outrefs { () }
2438              
2439 9     9   57 package Devel::MAT::SV::INVLIST 0.49;
  9         10  
  9         728  
2440 9     9   48 use base qw( Devel::MAT::SV );
  9         13  
  9         974  
2441             use constant basetype => "INVLIST";
2442             __PACKAGE__->register_type( 12 );
2443       539      
2444             sub load {}
2445 154     154   1282  
2446             sub desc { "INVLIST()" }
2447 159     159   285  
2448             sub _outrefs { () }
2449              
2450             # A hack to compress files
2451 9     9   74 package Devel::MAT::SV::_UNDEFSV 0.49;
  9         27  
  9         3300  
2452             use base qw( Devel::MAT::SV::SCALAR );
2453             __PACKAGE__->register_type( 13 );
2454              
2455             sub load
2456 152864     152864   177512 {
2457             my $self = shift;
2458 152864         191050  
2459             bless $self, "Devel::MAT::SV::SCALAR";
2460 152864         306428  
2461             $self->_set_scalar_fields( 0, 0, 0,
2462             "", 0,
2463             0,
2464             );
2465             }
2466              
2467 9     9   64 package Devel::MAT::SV::_YESSV 0.49;
  9         15  
  9         2928  
2468             use base qw( Devel::MAT::SV::BOOL );
2469             __PACKAGE__->register_type( 14 );
2470              
2471             sub load
2472 0     0     {
2473             my $self = shift;
2474 0            
2475             bless $self, "Devel::MAT::SV::BOOL";
2476 0            
2477             $self->_set_scalar_fields( 0x01, 1, 1.0,
2478             "1", 1,
2479             0,
2480             );
2481             }
2482              
2483 9     9   56 package Devel::MAT::SV::_NOSV 0.49;
  9         13  
  9         2537  
2484             use base qw( Devel::MAT::SV::BOOL );
2485             __PACKAGE__->register_type( 15 );
2486              
2487             sub load
2488 0     0     {
2489             my $self = shift;
2490 0            
2491             bless $self, "Devel::MAT::SV::BOOL";
2492 0            
2493             $self->_set_scalar_fields( 0x01, 0, 0,
2494             "", 0,
2495             0,
2496             );
2497             }
2498              
2499 9     9   64 package Devel::MAT::SV::OBJECT 0.49;
  9         15  
  9         841  
2500             use base qw( Devel::MAT::SV );
2501 9     9   50 __PACKAGE__->register_type( 16 );
  9         12  
  9         751  
2502 9     9   48 use constant $CONSTANTS;
  9         13  
  9         4975  
2503             use constant basetype => "OBJ";
2504              
2505             =head1 Devel::MAT::SV::OBJECT
2506              
2507             Represents an object instance; an SV of type C. These are only
2508             present in files from perls with C.
2509              
2510             =cut
2511              
2512             sub load
2513 0     0     {
2514 0           my $self = shift;
2515 0           my ( $header, $ptrs, $strs ) = @_;
2516             my $df = $self->df;
2517 0            
2518             my ( $n ) =
2519             unpack "$df->{uint_fmt} a*", $header;
2520 0 0          
2521 0           my @fields_at = $n ? $df->_read_ptrs( $n ) : ();
2522             $self->_set_object_fields( \@fields_at );
2523             }
2524              
2525             =head2 fields
2526              
2527             @svs = $obj->fields
2528              
2529             Returns all the values of all the fields in a list.
2530              
2531             Note that to find the names of the fields you'll have to enquire with the
2532             class
2533              
2534             =cut
2535              
2536             sub fields
2537 0     0     {
2538             my $self = shift;
2539 0            
2540 0 0         my $n = $self->n_fields;
2541             return $n unless wantarray;
2542 0            
2543 0           my $df = $self->df;
  0            
2544             return map { $df->sv_at( $self->field_at( $_ ) ) } 0 .. $n-1;
2545             }
2546              
2547             =head2 field
2548              
2549             $sv = $obj->field( $name_or_fieldix )
2550              
2551             Returns the value of the given field; which may be specified by name or
2552             index directly.
2553              
2554             =cut
2555              
2556             sub field
2557 0     0     {
2558 0           my $self = shift;
2559             my ( $name_or_fieldix ) = @_;
2560 0            
2561 0 0         my $fieldix;
2562 0           if( $name_or_fieldix =~ m/^\d+$/ ) {
2563             $fieldix = $name_or_fieldix;
2564             }
2565 0           else {
2566             $fieldix = $self->blessed->field( $name_or_fieldix )->fieldix;
2567             }
2568 0            
2569             return $self->df->sv_at( $self->field_at( $fieldix ) );
2570             }
2571              
2572             sub desc
2573 0     0     {
2574             my $self = shift;
2575 0            
2576             return "OBJ()";
2577             }
2578              
2579             sub _outrefs
2580 0     0     {
2581 0           my $self = shift;
2582             my ( $match, $no_desc ) = @_;
2583 0            
2584             my $n = $self->n_fields;
2585 0            
2586             my @outrefs;
2587 0            
2588 0 0         foreach my $field ( $self->blessed->fields ) {
2589             my $sv = $self->field( $field->fieldix ) or next;
2590 0 0          
2591             my $name = $no_desc ? undef :
2592 0 0         "the " . Devel::MAT::Cmd->format_note( $field->name, 1 ) . " field";
2593 0 0         if( $match & STRENGTH_STRONG ) {
2594             push @outrefs, $no_desc ? ( strong => $sv ) :
2595             Devel::MAT::SV::Reference( $name, strong => $sv );
2596 0 0 0       }
      0        
      0        
2597 0 0         if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
2598             push @outrefs, $no_desc ? ( indirect => $rv ) :
2599             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
2600             }
2601             }
2602 0            
2603             return @outrefs;
2604             }
2605              
2606 9     9   57 package Devel::MAT::SV::CLASS 0.49;
  9         18  
  9         2474  
2607             use base qw( Devel::MAT::SV::STASH );
2608 9     9   54 __PACKAGE__->register_type( 17 );
  9         14  
  9         621  
2609             use constant $CONSTANTS;
2610 9     9   46  
  9         14  
  9         676  
2611             use Carp;
2612 9     9   49  
  9         166  
  9         51  
2613             use Struct::Dumb 0.07 qw( readonly_struct );
2614             readonly_struct Field => [qw( fieldix name )];
2615 9     9   643  
  9         23  
  9         6003  
2616             use List::Util qw( first );
2617              
2618             =head1 Devel::MAT::SV::CLASS
2619              
2620             Represents a class; a sub-type of stash for implementing object classes. These
2621             are only present in files from perls with C.
2622              
2623             =cut
2624              
2625             sub load
2626 0     0     {
2627 0           my $self = shift;
2628 0           my ( $header, $ptrs, $strs ) = @_;
2629             my $df = $self->df;
2630 0            
  0            
2631             my ( $stash_bytes, $stash_ptrs, $stash_strs ) = @{ $df->{sv_sizes}[6] };
2632 0            
2633             $self->SUPER::load(
2634             substr( $header, 0, $stash_bytes, "" ),
2635             [ splice @$ptrs, 0, $stash_ptrs ],
2636             [ splice @$strs, 0, $stash_strs ],
2637             );
2638 0            
  0            
2639             @{$self}{qw( adjust_blocks_at )} =
2640             @$ptrs;
2641 0            
2642             while( my $type = $df->_read_u8 ) {
2643 0           match( $type : == ) {
  0            
2644 0 0         case( 1 ) { push @{ $self->{fields} }, [ $df->_read_uint, $df->_read_str ] }
2645 0           default {
2646             die "TODO: unhandled CLASSx type $type";
2647             }
2648             }
2649             }
2650             }
2651 0     0      
  0            
2652             sub adjust_blocks { my $self = shift; return $self->df->sv_at( $self->{adjust_blocks_at} ) }
2653              
2654             =head2 fields
2655              
2656             @fields = $class->fields
2657              
2658             Returns a list of the field definitions of the class, in declaration order.
2659             Each is a structure whose form is given below.
2660              
2661             =cut
2662              
2663             sub fields
2664 0     0     {
2665 0           my $self = shift;
  0            
  0            
2666             return map { Field( @$_ ) } @{ $self->{fields} };
2667             }
2668              
2669             =head2 field
2670              
2671             $field = $class->field( $name_or_fieldix )
2672              
2673             Returns the field definition of the given field; which may be specified by
2674             name or index directly. Throws an exception if none such exists.
2675              
2676             The returned field is a structure of the following fields:
2677              
2678             $fieldix = $field->fieldix
2679             $name = $field->name
2680              
2681             =head2 maybe_field
2682              
2683             $field = $class->maybe_field( $name_or_fieldix )
2684              
2685             I
2686              
2687             Similar to L but returns undef if none such exists.
2688              
2689             =cut
2690              
2691             sub maybe_field
2692 0     0     {
2693 0           my $self = shift;
2694             my ( $name_or_fieldix ) = @_;
2695 0 0          
2696 0     0     if( $name_or_fieldix =~ m/^\d+$/ ) {
  0            
2697             return first { $_->fieldix == $name_or_fieldix } $self->fields;
2698             }
2699 0     0     else {
  0            
2700             return first { $_->name eq $name_or_fieldix } $self->fields
2701             }
2702             }
2703              
2704             sub field
2705 0     0     {
2706 0   0       my $self = shift;
2707 0           return $self->maybe_field( @_ ) // do {
2708 0 0         my ( $name_or_fieldix ) = @_;
2709 0           croak "No field at index $name_or_fieldix" if $name_or_fieldix =~ m/^\d+$/;
2710             croak "No field named '$name_or_fieldix'";
2711             };
2712             }
2713              
2714             sub _outrefs
2715 0     0     {
2716 0           my $self = shift;
2717             my ( $match, $no_desc ) = @_;
2718 0            
2719             my @outrefs = $self->SUPER::_outrefs( @_ );
2720 0 0          
2721 0 0         if( $match & STRENGTH_STRONG ) {
2722 0 0         if( my $sv = $self->adjust_blocks ) {
2723             push @outrefs, $no_desc ? ( strong => $sv ) :
2724             Devel::MAT::SV::Reference( "the ADJUST blocks AV", strong => $sv );
2725             }
2726             }
2727 0            
2728             return @outrefs;
2729             }
2730              
2731             # A "SV" type that isn't really an SV, but has many of the same methods. These
2732             # aren't created by core perl, but are used by XS extensions
2733 9     9   67 package Devel::MAT::SV::C_STRUCT 0.49;
  9         24  
  9         820  
2734             use base qw( Devel::MAT::SV );
2735 9     9   48 __PACKAGE__->register_type( 0x7F );
  9         16  
  9         792  
2736             use constant $CONSTANTS;
2737 9         584 use constant {
2738             FIELD_PTR => 0x00,
2739             FIELD_BOOL => 0x01,
2740             FIELD_U8 => 0x02,
2741             FIELD_U32 => 0x03,
2742 9     9   51 FIELD_UINT => 0x04,
  9         14  
2743 9     9   47 };
  9         36  
  9         896  
2744 9     9   50 use Carp;
  9         13  
  9         6576  
2745             use List::Util qw( first );
2746              
2747             =head1 Devel::MAT::SV::C_STRUCT
2748              
2749             Represents a C-level c type.
2750              
2751             =cut
2752              
2753             sub desc
2754 0     0     {
2755 0           my $self = shift;
2756             my $typename = $self->structtype->name;
2757 0            
2758             "C_STRUCT($typename)";
2759             }
2760              
2761             sub load
2762 0     0     {
2763 0           my $self = shift;
2764             my ( $fields ) = @_;
2765 0            
2766             my $df = $self->df;
2767 0            
2768             my @vals;
2769 0            
2770 0           foreach my $field ( @$fields ) {
2771             push @vals, my $type = $field->type;
2772 0 0 0        
    0          
    0          
    0          
2773 0           if( $type == FIELD_PTR ) {
2774             push @vals, $df->_read_ptr;
2775             }
2776 0           elsif( $type == FIELD_BOOL or $type == FIELD_U8 ) {
2777             push @vals, $df->_read_u8;
2778             }
2779 0           elsif( $type == FIELD_U32 ) {
2780             push @vals, $df->_read_u32;
2781             }
2782 0           elsif( $type == FIELD_UINT ) {
2783             push @vals, $df->_read_uint;
2784             }
2785 0           else {
2786             croak "TODO: load struct field type = $type\n";
2787             }
2788             }
2789 0            
2790             $self->_set_struct_fields( @vals );
2791             }
2792              
2793             =head2 fields
2794              
2795             @kvlist = $struct->fields
2796              
2797             Returns an even-sized name/value list of all the field values stored by the
2798             struct; each preceeded by its field type structure.
2799              
2800             =cut
2801              
2802             sub fields
2803 0     0     {
2804             my $self = shift;
2805 0            
2806             my $df = $self->df;
2807 0            
2808             my $fields = $self->structtype->fields;
2809              
2810 0           return map {
  0            
2811             my $field = $fields->[$_];
2812 0 0          
2813 0           if( $field->type == FIELD_PTR ) {
2814             $field => $df->sv_at( $self->field( $_ ) )
2815             }
2816 0           else {
2817             $field => $self->field( $_ );
2818             }
2819             } 0 .. $#$fields;
2820             }
2821              
2822             =head2 field_named
2823              
2824             $val = $struct->field_named( $name )
2825              
2826             Looks for a field whose name is exactly that given, and returns its value.
2827              
2828             Throws an exception if the struct has no such field of that name.
2829              
2830             =head2 maybe_field_named
2831              
2832             $val = $struct->maybe_field_named( $name )
2833              
2834             I
2835              
2836             As L but returns C if there is no such field.
2837              
2838             =cut
2839              
2840             sub maybe_field_named
2841 0     0     {
2842 0           my $self = shift;
2843             my ( $name ) = @_;
2844 0            
2845             my $fields = $self->structtype->fields;
2846 0 0   0      
  0            
2847             defined( my $idx = first { $fields->[$_]->name eq $name } 0 .. $#$fields )
2848             or return undef;
2849 0            
2850             my $field = $fields->[$idx];
2851 0 0          
2852 0           if( $field->type == FIELD_PTR ) {
2853             return $self->df->sv_at( $self->field( $idx ) );
2854             }
2855 0           else {
2856             return $self->field( $idx );
2857             }
2858             }
2859              
2860             sub field_named
2861 0     0     {
2862 0           my $self = shift;
2863             my ( $name ) = @_;
2864 0   0        
2865             return $self->maybe_field_named( $name ) // croak "No field named $name";
2866             }
2867              
2868             =head2 structtype
2869              
2870             $structtype = $struct->structtype
2871              
2872             Returns a metadata structure describing the type of the struct itself.
2873              
2874             Has the following named accessors
2875              
2876             =over 4
2877              
2878             =item name => STRING
2879              
2880             The name of the struct type, as given by the dumpfile.
2881              
2882             =item fields => ARRAY[ Field ]
2883              
2884             An ARRAY reference containing the definitions of each field in turn
2885              
2886             =back
2887              
2888             =cut
2889              
2890             sub structtype
2891 0     0     {
2892 0           my $self = shift;
2893             return $self->df->structtype( $self->structid );
2894             }
2895              
2896             sub _outrefs
2897 0     0     {
2898 0           my $self = shift;
2899             my ( $match, $no_desc ) = @_;
2900 0 0          
2901             return unless $match & STRENGTH_STRONG;
2902 0            
2903             my $df = $self->df;
2904 0            
2905             my @outrefs;
2906 0            
2907 0           my $fields = $self->structtype->fields;
2908 0           foreach my $idx ( 0 .. $#$fields ) {
2909 0 0         my $field = $fields->[$idx];
2910             $field->type == FIELD_PTR or next; # Is PTR
2911 0 0          
2912             my $sv = $df->sv_at( $self->field( $idx ) ) or next;
2913 0 0          
2914             push @outrefs, $no_desc ? ( strong => $sv ) :
2915             Devel::MAT::SV::Reference( $field->name, strong => $sv );
2916             }
2917 0            
2918             return @outrefs;
2919             }
2920              
2921             =head1 AUTHOR
2922              
2923             Paul Evans
2924              
2925             =cut
2926              
2927             0x55AA;