File Coverage

blib/lib/Devel/MAT/SV.pm
Criterion Covered Total %
statement 792 1099 72.0
branch 282 482 58.5
condition 72 146 49.3
subroutine 193 276 69.9
pod 17 23 73.9
total 1356 2026 66.9


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.51;
7              
8 9     9   108 use v5.14;
  9         32  
9 9     9   47 use warnings;
  9         17  
  9         224  
10              
11 9     9   41 use Carp;
  9         18  
  9         521  
12 9     9   68 use Scalar::Util qw( weaken );
  9         25  
  9         387  
13              
14 9     9   574 use Syntax::Keyword::Match;
  9         1863  
  9         89  
15              
16             # Load XS code
17             require Devel::MAT;
18              
19 9     9   642 use constant immortal => 0;
  9         26  
  9         967  
20              
21 9     9   66 use List::Util qw( first );
  9         28  
  9         733  
22              
23 9     9   4382 use Struct::Dumb 0.07 qw( readonly_struct );
  9         24371  
  9         50  
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   1288 $CONSTANTS = {
42             STRENGTH_STRONG => (1 << 0),
43             STRENGTH_WEAK => (1 << 1),
44             STRENGTH_INDIRECT => (1 << 2),
45             STRENGTH_INFERRED => (1 << 3),
46             };
47 9         31 $CONSTANTS->{STRENGTH_DIRECT} = $CONSTANTS->{STRENGTH_STRONG}|$CONSTANTS->{STRENGTH_WEAK};
48 9         214 $CONSTANTS->{STRENGTH_ALL} = $CONSTANTS->{STRENGTH_STRONG}|$CONSTANTS->{STRENGTH_WEAK}|$CONSTANTS->{STRENGTH_INDIRECT}|$CONSTANTS->{STRENGTH_INFERRED};
49             }
50 9     9   228 use constant $CONSTANTS;
  9         30  
  9         1552  
51              
52             my %types;
53             sub register_type
54             {
55 171     171 0 540 $types{$_[1]} = $_[0];
56             # generate the ->type constant method
57 171         577 ( my $typename = $_[0] ) =~ s/^Devel::MAT::SV:://;
58 9     9   67 no strict 'refs';
  9         19  
  9         17127  
59 171 100   0   336 *{"$_[0]::type"} = sub () { $typename } unless defined *{"$_[0]::type"}{CODE};
  162         581  
  0         0  
  171         1632  
60             }
61              
62             sub new
63             {
64 573465     573465 0 821896 shift;
65 573465         962249 my ( $type, $df, $header, $ptrs, $strs ) = @_;
66              
67 573465 50       1246976 my $class = $types{$type} or croak "Cannot load unknown SV type $type";
68              
69 573465         1032685 my $self = bless {}, $class;
70              
71 573465         3089138 $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 573465         1286007 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 180875     180875 1 238318 my $self = shift;
167 180875         539794 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 29484     29484 1 40160 my $self = shift;
241 29484 100       171428 return unless my $magic = $self->{magic};
242              
243 481         998 my $df = $self->df;
244             return map {
245 481         861 my ( undef, undef, $obj_at, $ptr_at ) = @$_;
  481         1015  
246 481 100       1392 ( $obj_at ? ( $df->sv_at( $obj_at ) ) : () ),
    100          
247             ( $ptr_at ? ( $df->sv_at( $ptr_at ) ) : () )
248             } @$magic;
249             }
250              
251             =head2 backrefs
252              
253             $av_or_rv = $sv->backrefs
254              
255             Returns backrefs SV, which may be an AV containing the back references, or
256             if there is only one, the REF SV itself referring to this.
257              
258             =cut
259              
260             sub backrefs
261             {
262 1     1 1 12 my $self = shift;
263              
264 1 50       4 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       7 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 15 my $self = shift;
287 4         19 return $self->{rootname};
288             }
289              
290             # internal
291             sub more_magic
292             {
293 41871     41871 0 58254 my $self = shift;
294 41871         70151 my ( $type, $flags, $obj_at, $ptr_at, $vtbl_ptr ) = @_;
295              
296 41871         53795 push @{ $self->{magic} }, [ $type => $flags, $obj_at, $ptr_at, $vtbl_ptr ];
  41871         187823  
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 180886     180886   252106 my $self = shift;
368 180886         314123 my ( $match, $no_desc ) = @_;
369              
370             # In scalar context we're just counting so we might as well count just SVs
371 180886   66     342791 $no_desc ||= !wantarray;
372              
373 180886         360883 my @outrefs = $self->_outrefs( $match, $no_desc );
374              
375 180886 100 100     496249 if( $match & STRENGTH_WEAK and my $blessed = $self->blessed ) {
376 1407 100       3283 push @outrefs, $no_desc ? ( weak => $blessed ) :
377             Reference( "the bless package", weak => $blessed );
378             }
379              
380 180886 100       258715 foreach my $mg ( @{ $self->{magic} || [] } ) {
  180886         665389  
381 17032         73187 my ( $type, $flags, $obj_at, $ptr_at ) = @$mg;
382              
383 17032 100       44121 if( my $obj = $self->df->sv_at( $obj_at ) ) {
384 15381         27034 my $is_strong = ( $flags & 0x01 );
385 15381 100       40117 if( $match & ( $is_strong ? STRENGTH_STRONG : STRENGTH_WEAK ) ) {
    50          
386 15381 100       28474 my $strength = $is_strong ? "strong" : "weak";
387 15381 100       44800 push @outrefs, $no_desc ? ( $strength => $obj ) :
388             Reference( "'$type' magic object", $strength => $obj );
389             }
390             }
391              
392 17032 100 66     87808 if( $match & STRENGTH_STRONG and my $ptr = $self->df->sv_at( $ptr_at ) ) {
393 4 50       26 push @outrefs, $no_desc ? ( strong => $ptr ) :
394             Reference( "'$type' magic pointer", strong => $ptr );
395             }
396             }
397              
398 180886 50       255280 foreach my $ann ( @{ $self->{annotations} || [] } ) {
  180886         507699  
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 180886 50       330953 return @outrefs / 2 if !wantarray;
407 180886         1470961 return @outrefs;
408             }
409              
410 180870     180870 1 341263 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 36 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 39 sub outrefs_direct { $_[0]->_outrefs_matching( STRENGTH_DIRECT, $_[1] ) }
448 1     1 1 2679 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 701 my $self = shift;
474 2         5 my ( $name ) = @_;
475              
476 2     3   14 return first { $_->name eq $name } $self->outrefs;
  3         14  
477             }
478              
479             sub outref_named
480             {
481 1     1 1 2640 my $self = shift;
482 1         2 my ( $name ) = @_;
483              
484 1   33     7 return $self->maybe_outref_named( $name ) // croak "No outref named $name";
485             }
486              
487             =head2 is_mortal
488              
489             $mortal = $sv->is_mortal
490              
491             Returns true if this SV is referenced by the temps stack.
492              
493             =cut
494              
495             sub _set_is_mortal
496             {
497 3     3   9 my $self = shift;
498 3         14 $self->{is_mortal} = 1;
499             }
500              
501             sub is_mortal
502             {
503 3384     3384 1 8211 my $self = shift;
504 3384         14128 return $self->{is_mortal};
505             }
506              
507             =head1 IMMORTAL SVs
508              
509             Three special SV objects exist outside of the heap, to represent C and
510             boolean true and false. They are
511              
512             =over 4
513              
514             =item * Devel::MAT::SV::UNDEF
515              
516             =item * Devel::MAT::SV::YES
517              
518             =item * Devel::MAT::SV::NO
519              
520             =back
521              
522             =cut
523              
524             package Devel::MAT::SV::Immortal 0.51;
525 9     9   77 use base qw( Devel::MAT::SV );
  9         28  
  9         1274  
526 9     9   65 use constant immortal => 1;
  9         26  
  9         593  
527 9     9   57 use constant basetype => "SV";
  9         19  
  9         1420  
528             sub new {
529 21     21   40 my $class = shift;
530 21         43 my ( $df, $addr ) = @_;
531 21         47 my $self = bless {}, $class;
532 21         177 $self->_set_core_fields( 0, $df, $addr, 0, 0, 0 );
533 21         80 return $self;
534             }
535 3     3   10 sub _outrefs { () }
536              
537             package Devel::MAT::SV::UNDEF 0.51;
538 9     9   73 use base qw( Devel::MAT::SV::Immortal );
  9         39  
  9         3769  
539 0     0   0 sub desc { "UNDEF" }
540 1662     1662   5364 sub type { "UNDEF" }
541              
542             package Devel::MAT::SV::YES 0.51;
543 9     9   81 use base qw( Devel::MAT::SV::Immortal );
  9         20  
  9         3583  
544 0     0   0 sub desc { "YES" }
545 993     993   3122 sub type { "SCALAR" }
546              
547             # Pretend to be 1 / "1"
548 0     0   0 sub uv { 1 }
549 0     0   0 sub iv { 1 }
550 0     0   0 sub nv { 1.0 }
551 0     0   0 sub pv { "1" }
552 0     0   0 sub rv { undef }
553 0     0   0 sub is_weak { '' }
554              
555             package Devel::MAT::SV::NO 0.51;
556 9     9   70 use base qw( Devel::MAT::SV::Immortal );
  9         18  
  9         3501  
557 0     0   0 sub desc { "NO" }
558 0     0   0 sub type { "SCALAR" }
559              
560             # Pretend to be 0 / ""
561 0     0   0 sub uv { 0 }
562 0     0   0 sub iv { 0 }
563 0     0   0 sub nv { 0.0 }
564 0     0   0 sub pv { "0" }
565 0     0   0 sub rv { undef }
566 0     0   0 sub is_weak { '' }
567              
568             package Devel::MAT::SV::Unknown 0.51;
569 9     9   75 use base qw( Devel::MAT::SV );
  9         18  
  9         1398  
570             __PACKAGE__->register_type( 0xff );
571              
572 0     0   0 sub desc { "UNKNOWN" }
573              
574       0     sub _outrefs {}
575              
576             package Devel::MAT::SV::GLOB 0.51;
577 9     9   62 use base qw( Devel::MAT::SV );
  9         17  
  9         864  
578             __PACKAGE__->register_type( 1 );
579 9     9   57 use constant $CONSTANTS;
  9         17  
  9         909  
580 9     9   66 use constant basetype => "GV";
  9         16  
  9         9806  
581              
582             =head1 Devel::MAT::SV::GLOB
583              
584             Represents a glob; an SV of type C.
585              
586             =cut
587              
588             sub load
589             {
590 53834     53834   85479 my $self = shift;
591 53834         88986 my ( $header, $ptrs, $strs ) = @_;
592 53834         109426 my $df = $self->df;
593              
594 53834         117091 my ( $line ) =
595             unpack "$df->{uint_fmt}", $header;
596              
597             $self->_set_glob_fields(
598 53834         86206 @{$ptrs}[0..7],
  53834         272320  
599             $line, $strs->[1],
600             $strs->[0],
601             );
602             }
603              
604             sub _fixup
605             {
606 53834     53834   69187 my $self = shift;
607              
608 53834   66     80780 $_ and $_->_set_glob_at( $self->addr ) for $self->scalar, $self->array, $self->hash, $self->code;
609             }
610              
611             =head2 file
612              
613             =head2 line
614              
615             =head2 location
616              
617             $file = $gv->file
618              
619             $line = $gv->line
620              
621             $location = $gv->location
622              
623             Returns the filename, line number, or combined location (C)
624             that the GV first appears at.
625              
626             =head2 name
627              
628             $name = $gv->name
629              
630             Returns the value of the C field, for named globs.
631              
632             =cut
633              
634             # XS accessors
635              
636             sub location
637             {
638 0     0   0 my $self = shift;
639 0         0 my $file = $self->file;
640 0         0 my $line = $self->line;
641 0 0       0 defined $file ? "$file line $line" : undef
642             }
643              
644             =head2 stash
645              
646             $stash = $gv->stash
647              
648             Returns the stash to which the GV belongs.
649              
650             =cut
651              
652 27     27   44 sub stash { my $self = shift; $self->df->sv_at( $self->stash_at ) }
  27         91  
653              
654             =head2 scalar
655              
656             =head2 array
657              
658             =head2 hash
659              
660             =head2 code
661              
662             =head2 egv
663              
664             =head2 io
665              
666             =head2 form
667              
668             $sv = $gv->scalar
669              
670             $av = $gv->array
671              
672             $hv = $gv->hash
673              
674             $cv = $gv->code
675              
676             $gv = $gv->egv
677              
678             $io = $gv->io
679              
680             $form = $gv->form
681              
682             Return the SV in the various glob slots.
683              
684             =cut
685              
686 96983     96983   127117 sub scalar { my $self = shift; $self->df->sv_at( $self->scalar_at ) }
  96983         367611  
687 96978     96978   127012 sub array { my $self = shift; $self->df->sv_at( $self->array_at ) }
  96978         249489  
688 97322     97322   128243 sub hash { my $self = shift; $self->df->sv_at( $self->hash_at ) }
  97322         243038  
689 96983     96983   126034 sub code { my $self = shift; $self->df->sv_at( $self->code_at ) }
  96983         242789  
690 35800     35800   51094 sub egv { my $self = shift; $self->df->sv_at( $self->egv_at ) }
  35800         95957  
691 43138     43138   61602 sub io { my $self = shift; $self->df->sv_at( $self->io_at ) }
  43138         120066  
692 43137     43137   56453 sub form { my $self = shift; $self->df->sv_at( $self->form_at ) }
  43137         116023  
693              
694             sub stashname
695             {
696 27     27   45 my $self = shift;
697 27         74 my $name = $self->name;
698 27         82 $name =~ s(^([\x00-\x1f])){"^" . chr(64 + ord $1)}e;
  0         0  
699 27         58 return $self->stash->stashname . "::" . $name;
700             }
701              
702             sub desc
703             {
704 15382     15382   66805 my $self = shift;
705 15382         19638 my $sigils = "";
706 15382 100       24618 $sigils .= '$' if $self->scalar;
707 15382 100       27522 $sigils .= '@' if $self->array;
708 15382 100       25753 $sigils .= '%' if $self->hash;
709 15382 100       25747 $sigils .= '&' if $self->code;
710 15382 100       26231 $sigils .= '*' if $self->egv;
711 15382 100       26038 $sigils .= 'I' if $self->io;
712 15382 50       25860 $sigils .= 'F' if $self->form;
713              
714 15382         38258 return "GLOB($sigils)";
715             }
716              
717             sub _outrefs
718             {
719 20418     20418   32171 my $self = shift;
720 20418         35516 my ( $match, $no_desc ) = @_;
721              
722 20418         26185 my @outrefs;
723              
724 20418 50       40719 if( $match & STRENGTH_STRONG ) {
725 20418         37541 foreach my $slot (qw( scalar array hash code io form )) {
726 122508 100       276409 my $sv = $self->$slot or next;
727 19418 100       66829 push @outrefs, $no_desc ? ( strong => $sv ) :
728             Devel::MAT::SV::Reference( "the $slot", strong => $sv );
729             }
730             }
731              
732 20418 100       42511 if( my $egv = $self->egv ) {
733             # the egv is weakref if if it points back to itself
734 20410         40974 my $egv_is_self = $egv == $self;
735              
736 20410 100       59508 if( $match & ( $egv_is_self ? STRENGTH_WEAK : STRENGTH_STRONG ) ) {
    50          
737 20410 100       40812 my $strength = $egv_is_self ? "weak" : "strong";
738 20410 100       48648 push @outrefs, $no_desc ? ( $strength => $egv ) :
739             Devel::MAT::SV::Reference( "the egv", $strength => $egv );
740             }
741             }
742              
743 20418         50443 foreach my $saved ( @{ $self->{saved} } ) {
  20418         64089  
744 4         15 my $sv = $self->df->sv_at( $saved->[1] );
745              
746 4 50       28 push @outrefs, $no_desc ? ( inferred => $sv ) :
747             Devel::MAT::SV::Reference( "saved value of " . Devel::MAT::Cmd->format_note( $saved->[0] ) . " slot",
748             "inferred", $sv );
749             }
750              
751 20418         52615 return @outrefs;
752             }
753              
754             sub _more_saved
755             {
756 5     5   12 my $self = shift;
757 5         10 my ( $slot, $addr ) = @_;
758              
759 5         9 push @{ $self->{saved} }, [ $slot => $addr ];
  5         23  
760             }
761              
762             package Devel::MAT::SV::SCALAR 0.51;
763 9     9   68 use base qw( Devel::MAT::SV );
  9         19  
  9         1029  
764             __PACKAGE__->register_type( 2 );
765 9     9   62 use constant $CONSTANTS;
  9         20  
  9         998  
766 9     9   62 use constant basetype => "SV";
  9         17  
  9         7930  
767              
768             =head1 Devel::MAT::SV::SCALAR
769              
770             Represents a non-referential scalar value; an SV of any of the types up to and
771             including C (that is, C, C, C, C, C or
772             C). This includes all numbers, integers and floats, strings, and dualvars
773             containing multiple parts.
774              
775             =cut
776              
777             sub load
778             {
779 217609     217609   335166 my $self = shift;
780 217609         347135 my ( $header, $ptrs, $strs ) = @_;
781 217609         421400 my $df = $self->df;
782              
783 217609         845698 my ( $flags, $uv, $nvbytes, $pvlen ) =
784             unpack "C $df->{uint_fmt} A$df->{nv_len} $df->{uint_fmt}", $header;
785 217609         465794 my $nv = unpack "$df->{nv_fmt}", $nvbytes;
786              
787             # $strs->[0] will be swiped
788              
789 217609         560056 $self->_set_scalar_fields( $flags, $uv, $nv,
790             $strs->[0], $pvlen,
791             $ptrs->[0], # OURSTASH
792             );
793              
794             # $strs->[0] is now undef
795              
796 217609         301787 $flags &= ~0x1f;
797 217609 50       545165 $flags and die sprintf "Unrecognised SCALAR flags %02x\n", $flags;
798             }
799              
800             =head2 uv
801              
802             $uv = $sv->uv
803              
804             Returns the integer numeric portion as an unsigned value, if valid, or C.
805              
806             =head2 iv
807              
808             $iv = $sv->iv
809              
810             Returns the integer numeric portion as a signed value, if valid, or C.
811              
812             =head2 nv
813              
814             $nv = $sv->nv
815              
816             Returns the floating numeric portion, if valid, or C.
817              
818             =head2 pv
819              
820             $pv = $sv->pv
821              
822             Returns the string portion, if valid, or C.
823              
824             =head2 pvlen
825              
826             $pvlen = $sv->pvlen
827              
828             Returns the length of the string portion, if valid, or C.
829              
830             =cut
831              
832             # XS accessors
833              
834             =head2 qq_pv
835              
836             $str = $sv->qq_pv( $maxlen )
837              
838             Returns the PV string, if defined, suitably quoted. If C<$maxlen> is defined
839             and the PV is longer than this, it is truncated and C<...> is appended after
840             the containing quote marks.
841              
842             =cut
843              
844             sub qq_pv
845             {
846 5     5   21 my $self = shift;
847 5         8 my ( $maxlen ) = @_;
848              
849 5 50       21 defined( my $pv = $self->pv ) or return undef;
850 5 100 66     24 $pv = substr( $pv, 0, $maxlen ) if defined $maxlen and $maxlen < length $pv;
851              
852 5         13 my $truncated = $self->pvlen > length $pv;
853              
854 5 100       19 if( $pv =~ m/^[\x20-\x7e]*$/ ) {
855 3         17 $pv =~ s/(['\\])/\\$1/g;
856 3         19 $pv = qq('$pv');
857             }
858             else {
859 2 50       10 $pv =~ s{(\") | (\r) | (\n) | ([\x00-\x1f\x80-\xff])}
  2 50       46  
    50          
860 2         11 {$1?'\\"' : $2?"\\r" : $3?"\\n" : sprintf "\\x%02x", ord $4}egx;
861             $pv = qq("$pv");
862 5 100       16 }
863             $pv .= "..." if $truncated;
864 5         21  
865             return $pv;
866             }
867              
868             =head2 ourstash
869              
870             $stash = $sv->ourstash
871              
872             Returns the stash of the SCALAR, if it is an 'C' variable.
873              
874             After perl 5.20 this is no longer used, and will return C.
875              
876             =cut
877 107829     107829   138198  
  107829         496217  
878             sub ourstash { my $self = shift; return $self->df->sv_at( $self->ourstash_at ) }
879              
880             sub symname
881 2     2   5 {
882 2 100       66 my $self = shift;
883 1         7 return unless my $glob_at = $self->glob_at;
884             return $mksymname->( '$', $self->df->sv_at( $glob_at ) );
885             }
886              
887             sub type
888 463771     463771   613626 {
889 463771 100 100     3235930 my $self = shift;
      100        
      100        
890 205579         598316 return "SCALAR" if defined $self->uv or defined $self->iv or defined $self->nv or defined $self->pv;
891             return "UNDEF";
892             }
893              
894             sub desc
895 107732     107732   446715 {
896             my $self = shift;
897 107732         127649  
898 107732 100       262892 my @flags;
899 107732 100       212526 push @flags, "UV" if defined $self->uv;
900 107732 100       202868 push @flags, "IV" if defined $self->iv;
901 107732 100       242264 push @flags, "NV" if defined $self->nv;
902 107732         157719 push @flags, "PV" if defined $self->pv;
903 107732 100       201250 local $" = ",";
904 62102         173966 return "UNDEF()" unless @flags;
905             return "SCALAR(@flags)";
906             }
907              
908             sub _outrefs
909 107829     107829   130953 {
910 107829         153539 my $self = shift;
911             my ( $match, $no_desc ) = @_;
912 107829         129038  
913             my @outrefs;
914 107829 50 33     236248  
915 0 0       0 if( $match & STRENGTH_STRONG and my $ourstash = $self->ourstash ) {
916             push @outrefs, $no_desc ? ( strong => $ourstash ) :
917             Devel::MAT::SV::Reference( "the our stash", strong => $ourstash );
918             }
919 107829         194988  
920             return @outrefs;
921             }
922              
923 9     9   70 package Devel::MAT::SV::REF 0.51;
  9         26  
  9         979  
924             use base qw( Devel::MAT::SV );
925 9     9   62 __PACKAGE__->register_type( 3 );
  9         32  
  9         852  
926 9     9   55 use constant $CONSTANTS;
  9         20  
  9         4230  
927             use constant basetype => "SV";
928              
929             =head1 Devel::MAT::SV::REF
930              
931             Represents a referential scalar; any SCALAR-type SV with the C flag
932             set.
933              
934             =cut
935              
936             sub load
937 26241     26241   42180 {
938 26241         45476 my $self = shift;
939             my ( $header, $ptrs, $strs ) = @_;
940 26241         46184  
941             ( my $flags ) =
942             unpack "C", $header;
943              
944 26241         38560 $self->_set_ref_fields(
  26241         81123  
945             @{$ptrs}[0,1], # RV, OURSTASH
946             $flags & 0x01, # RV_IS_WEAK
947             );
948 26241         41241  
949 26241 50       63717 $flags &= ~0x01;
950             $flags and die sprintf "Unrecognised REF flags %02x\n", $flags;
951             }
952              
953             =head2 rv
954              
955             $svrv = $sv->rv
956              
957             Returns the SV referred to by the reference.
958              
959             =cut
960 19071     19071   27129  
  19071         64095  
961             sub rv { my $self = shift; return $self->df->sv_at( $self->rv_at ) }
962              
963             =head2 is_weak
964              
965             $weak = $sv->is_weak
966              
967             Returns true if the SV is a weakened RV reference.
968              
969             =cut
970              
971             # XS accessor
972              
973             =head2 ourstash
974              
975             $stash = $sv->ourstash
976              
977             Returns the stash of the SCALAR, if it is an 'C' variable.
978              
979             =cut
980 7526     7526   10224  
  7526         20927  
981             sub ourstash { my $self = shift; return $self->df->sv_at( $self->ourstash_at ) }
982              
983             sub desc
984 7496     7496   32749 {
985             my $self = shift;
986 7496 100       30321  
987             return sprintf "REF(%s)", $self->is_weak ? "W" : "";
988             }
989              
990             *symname = \&Devel::MAT::SV::SCALAR::symname;
991              
992             sub _outrefs
993 7526     7526   9596 {
994 7526         10901 my $self = shift;
995             my ( $match, $no_desc ) = @_;
996 7526         9908  
997             my @outrefs;
998 7526         21035  
999 7526 100 33     22759 my $is_weak = $self->is_weak;
    50          
1000 7526 100       14419 if( $match & ( $is_weak ? STRENGTH_WEAK : STRENGTH_STRONG ) and my $rv = $self->rv ) {
1001 7526 100       16095 my $strength = $is_weak ? "weak" : "strong";
1002             push @outrefs, $no_desc ? ( $strength => $rv ) :
1003             Devel::MAT::SV::Reference( "the referrant", $strength => $rv );
1004             }
1005 7526 50 33     19461  
1006 0 0       0 if( $match & STRENGTH_STRONG and my $ourstash = $self->ourstash ) {
1007             push @outrefs, $no_desc ? ( strong => $ourstash ) :
1008             Devel::MAT::SV::Reference( "the our stash", strong => $ourstash );
1009             }
1010 7526         19089  
1011             return @outrefs;
1012             }
1013              
1014 9     9   67 package Devel::MAT::SV::BOOL 0.51;
  9         18  
  9         3659  
1015             use base qw( Devel::MAT::SV::SCALAR );
1016 0     0   0  
1017             sub type { return "BOOL" }
1018              
1019             sub desc
1020 0     0   0 {
1021 0 0       0 my $self = shift;
1022 0         0 return "BOOL(YES)" if $self->uv;
1023             return "BOOL(NO)";
1024             }
1025              
1026 9     9   77 package Devel::MAT::SV::ARRAY 0.51;
  9         20  
  9         1104  
1027             use base qw( Devel::MAT::SV );
1028 9     9   64 __PACKAGE__->register_type( 4 );
  9         18  
  9         965  
1029 9     9   74 use constant $CONSTANTS;
  9         26  
  9         8655  
1030             use constant basetype => "AV";
1031              
1032             =head1 Devel::MAT::SV::ARRAY
1033              
1034             Represents an array; an SV of type C.
1035              
1036             =cut
1037              
1038             sub refcount_adjusted
1039 0     0   0 {
1040             my $self = shift;
1041 0 0       0 # AVs that are backrefs lists have an SvREFCNT artificially high
1042             return $self->refcnt - ( $self->is_backrefs ? 1 : 0 );
1043             }
1044              
1045             sub load
1046 56943     56943   83804 {
1047 56943         94840 my $self = shift;
1048 56943         111955 my ( $header, $ptrs, $strs ) = @_;
1049             my $df = $self->df;
1050 56943         152286  
1051             my ( $n, $flags ) =
1052             unpack "$df->{uint_fmt} C", $header;
1053 56943 100 100     235699  
1054             $self->_set_array_fields( $flags || 0, [ $n ? $df->_read_ptrs($n) : () ] );
1055             }
1056              
1057             sub _more_saved
1058 1     1   3 {
1059 1         4 my $self = shift;
1060             my ( $index, $addr ) = @_;
1061 1         3  
  1         6  
1062             push @{ $self->{saved} }, [ $index => $addr ];
1063             }
1064              
1065             =head2 is_unreal
1066              
1067             $unreal = $av->is_unreal
1068              
1069             Returns true if the C flag is not set on the array - i.e. that its
1070             SV pointers do not contribute to the C of the SVs it points at.
1071              
1072             =head2 is_backrefs
1073              
1074             $backrefs = $av->is_backrefs
1075              
1076             Returns true if the array contains the backrefs list of a hash or
1077             weakly-referenced object.
1078              
1079             =cut
1080              
1081             # XS accessors
1082              
1083             sub symname
1084 4     4   11 {
1085 4 100       41 my $self = shift;
1086 1         7 return unless my $glob_at = $self->glob_at;
1087             return $mksymname->( '@', $self->df->sv_at( $glob_at ) );
1088             }
1089              
1090             =head2 elems
1091              
1092             @svs = $av->elems
1093              
1094             Returns all of the element SVs in a list
1095              
1096             =cut
1097              
1098             sub elems
1099 22245     22245   37852 {
1100             my $self = shift;
1101 22245         55521  
1102 22245 100       59716 my $n = $self->n_elems;
1103             return $n unless wantarray;
1104 12878         30732  
1105 12878         145885 my $df = $self->df;
  5408950         11006738  
1106             return map { $df->sv_at( $self->elem_at( $_ ) ) } 0 .. $n-1;
1107             }
1108              
1109             =head2 elem
1110              
1111             $sv = $av->elem( $index )
1112              
1113             Returns the SV at the given index
1114              
1115             =cut
1116              
1117             sub elem
1118 4425967     4425967   5666413 {
1119 4425967         12150647 my $self = shift;
1120             return $self->df->sv_at( $self->elem_at( $_[0] ) );
1121             }
1122              
1123             sub desc
1124 9516     9516   42066 {
1125             my $self = shift;
1126 9516         23554  
1127             my @flags = $self->n_elems;
1128 9516 100       23104  
1129             push @flags, "!REAL" if $self->is_unreal;
1130 9516         12879  
1131 9516         27540 $" = ",";
1132             return "ARRAY(@flags)";
1133             }
1134              
1135             sub _outrefs
1136 12954     12954   22967 {
1137 12954         21986 my $self = shift;
1138             my ( $match, $no_desc ) = @_;
1139 12954         38549  
1140             my $n = $self->n_elems;
1141 12954         18332  
1142             my @outrefs;
1143 12954 100       37065  
1144 10535 50       27465 if( $self->is_unreal ) {
1145 10535         28409 if( $match & STRENGTH_WEAK ) {
1146 4374186 50       26494671 foreach my $idx ( 0 .. $n-1 ) {
1147             my $sv = $self->elem( $idx ) or next;
1148 4374186 100       10807498  
1149             push @outrefs, $no_desc ? ( weak => $sv ) :
1150             Devel::MAT::SV::Reference( "element " . Devel::MAT::Cmd->format_value( $idx, index => 1 ), weak => $sv );
1151             }
1152             }
1153             }
1154 2419         5624 else {
1155 25094 100       46143 foreach my $idx ( 0 .. $n-1 ) {
1156             my $sv = $self->elem( $idx ) or next;
1157 25002 100       51955  
1158             my $name = $no_desc ? undef :
1159 25002 100       46699 "element " . Devel::MAT::Cmd->format_value( $idx, index => 1 );
1160 25001 100       52526 if( $match & STRENGTH_STRONG ) {
1161             push @outrefs, $no_desc ? ( strong => $sv ) :
1162             Devel::MAT::SV::Reference( $name, strong => $sv );
1163 25002 50 100     128151 }
      66        
      66        
1164 2989 100       8395 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1165             push @outrefs, $no_desc ? ( indirect => $rv ) :
1166             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1167             }
1168             }
1169             }
1170 12954         50393  
  12954         50415  
1171 1         5 foreach my $saved ( @{ $self->{saved} } ) {
1172             my $sv = $self->df->sv_at( $saved->[1] );
1173 1 50       8  
1174             push @outrefs, $no_desc ? ( inferred => $sv ) :
1175             Devel::MAT::SV::Reference( "saved value of element " . Devel::MAT::Cmd->format_value( $saved->[0], index => 1 ),
1176             inferred => $sv );
1177             }
1178 12954         529222  
1179             return @outrefs;
1180             }
1181              
1182             package Devel::MAT::SV::PADLIST 0.51;
1183 9     9   65 # Synthetic type
  9         22  
  9         2798  
1184 9     9   65 use base qw( Devel::MAT::SV::ARRAY );
  9         19  
  9         451  
1185 9     9   54 use constant type => "PADLIST";
  9         16  
  9         3365  
1186             use constant $CONSTANTS;
1187              
1188             =head1 Devel::MAT::SV::PADLIST
1189              
1190             A subclass of ARRAY, this is used to represent the PADLIST of a CODE SV.
1191              
1192             =cut
1193 0     0   0  
  0         0  
1194             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1195              
1196             sub desc
1197 0     0   0 {
1198 0         0 my $self = shift;
1199             return "PADLIST(" . $self->n_elems . ")";
1200             }
1201              
1202             # Totally different outrefs format than ARRAY
1203             sub _outrefs
1204 0     0   0 {
1205 0         0 my $self = shift;
1206             my ( $match, $no_desc ) = @_;
1207 0         0  
1208             my @outrefs;
1209 0 0       0  
1210 0         0 if( $match & STRENGTH_STRONG ) {
1211 0         0 my $df = $self->df;
1212             my $n = $self->n_elems;
1213 0 0       0  
1214 0 0       0 if( my $padnames = $df->sv_at( $self->elem_at( 0 ) ) ) {
1215             push @outrefs, $no_desc ? ( strong => $padnames ) :
1216             Devel::MAT::SV::Reference( "the padnames", strong => $padnames );
1217             }
1218 0         0  
1219 0 0       0 foreach my $idx ( 1 .. $n-1 ) {
1220             my $pad = $df->sv_at( $self->elem_at( $idx ) ) or next;
1221 0 0       0  
1222             push @outrefs, $no_desc ? ( strong => $pad ) :
1223             Devel::MAT::SV::Reference( "pad at depth $idx", strong => $pad );
1224             }
1225             }
1226 0         0  
1227             return @outrefs;
1228             }
1229              
1230             package Devel::MAT::SV::PADNAMES 0.51;
1231 9     9   63 # Synthetic type
  9         17  
  9         2533  
1232 9     9   63 use base qw( Devel::MAT::SV::ARRAY );
  9         18  
  9         433  
1233 9     9   50 use constant type => "PADNAMES";
  9         18  
  9         4599  
1234             use constant $CONSTANTS;
1235              
1236             =head1 Devel::MAT::SV::PADNAMES
1237              
1238             A subclass of ARRAY, this is used to represent the PADNAMES of a CODE SV.
1239              
1240             =cut
1241 0     0   0  
  0         0  
1242             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1243              
1244             =head2 padname
1245              
1246             $padname = $padnames->padname( $padix )
1247              
1248             Returns the name of the lexical at the given index, or C
1249              
1250             =cut
1251              
1252             sub padname
1253 0     0   0 {
1254 0         0 my $self = shift;
1255 0 0       0 my ( $padix ) = @_;
1256 0 0       0 my $namepv = $self->elem( $padix ) or return undef;
1257 0         0 $namepv->type eq "SCALAR" or return undef;
1258             return $namepv->pv;
1259             }
1260              
1261             =head2 padix_from_padname
1262              
1263             $padix = $padnames->padix_from_padname( $padname )
1264              
1265             Returns the index of the lexical with the given name, or C
1266              
1267             =cut
1268              
1269             sub padix_from_padname
1270 0     0   0 {
1271 0         0 my $self = shift;
1272             my ( $padname ) = @_;
1273 0         0  
1274 0         0 foreach my $padix ( 1 .. scalar( $self->elems ) - 1 ) {
1275 0 0 0     0 my $namepv;
      0        
1276             return $padix if $namepv = $self->elem( $padix ) and
1277             $namepv->type eq "SCALAR" and
1278             $namepv->pv eq $padname;
1279             }
1280 0         0  
1281             return undef;
1282             }
1283              
1284             sub desc
1285 0     0   0 {
1286 0         0 my $self = shift;
1287             return "PADNAMES(" . scalar($self->elems) . ")";
1288             }
1289              
1290             # Totally different outrefs format than ARRAY
1291             sub _outrefs
1292 0     0   0 {
1293 0         0 my $self = shift;
1294             my ( $match, $no_desc ) = @_;
1295 0         0  
1296             my @outrefs;
1297 0 0       0  
1298 0         0 if( $match & STRENGTH_STRONG ) {
1299 0         0 my $df = $self->df;
1300             my $n = $self->n_elems;
1301 0         0  
1302 0 0       0 foreach my $idx ( 1 .. $n-1 ) {
1303             my $padname = $df->sv_at( $self->elem_at( $idx ) ) or next;
1304 0 0       0  
1305             push @outrefs, $no_desc ? ( strong => $padname ) :
1306             Devel::MAT::SV::Reference( "padname " . Devel::MAT::Cmd->format_value( $idx, index => 1 ), strong => $padname );
1307             }
1308             }
1309 0         0  
1310             return @outrefs;
1311             }
1312              
1313             package Devel::MAT::SV::PAD 0.51;
1314 9     9   69 # Synthetic type
  9         19  
  9         2548  
1315 9     9   65 use base qw( Devel::MAT::SV::ARRAY );
  9         16  
  9         481  
1316 9     9   92 use constant type => "PAD";
  9         17  
  9         6381  
1317             use constant $CONSTANTS;
1318              
1319             =head1 Devel::MAT::SV::PAD
1320              
1321             A subclass of ARRAY, this is used to represent a PAD of a CODE SV.
1322              
1323             =cut
1324              
1325             sub desc
1326 6751     6751   30088 {
1327 6751         11899 my $self = shift;
1328             return "PAD(" . scalar($self->elems) . ")";
1329             }
1330              
1331             =head2 padcv
1332              
1333             $cv = $pad->padcv
1334              
1335             Returns the C SV for which this is a pad.
1336              
1337             =cut
1338 6781     6781   10211  
  6781         31734  
1339             sub padcv { my $self = shift; return $self->df->sv_at( $self->padcv_at ) }
1340              
1341             =head2 lexvars
1342              
1343             ( $name, $sv, $name, $sv, ... ) = $pad->lexvars
1344              
1345             Returns a name/value list of the lexical variables in the pad.
1346              
1347             =cut
1348              
1349             sub lexvars
1350 0     0   0 {
1351 0         0 my $self = shift;
1352             my $padcv = $self->padcv;
1353 0         0  
1354             my @svs = $self->elems;
1355 0         0 return map {
  0         0  
1356 0 0       0 my $padname = $padcv->padname( $_ );
1357             $padname ? ( $padname->name => $svs[$_] ) : ()
1358             } 1 .. $#svs;
1359             }
1360              
1361             =head2 maybe_lexvar
1362              
1363             $sv = $pad->maybe_lexvar( $padname )
1364              
1365             I
1366              
1367             Returns the SV associated with the given padname if one exists, or C if
1368             not.
1369              
1370             Used to be named C.
1371              
1372             =cut
1373              
1374             sub maybe_lexvar
1375 4     4   10 {
1376 4         10 my $self = shift;
1377             my ( $padname ) = @_;
1378 4 50       14  
1379 4         60 my $padix = $self->padcv->padix_from_padname( $padname ) or return undef;
1380             return $self->elem( $padix );
1381             }
1382              
1383             *lexvar = \&maybe_lexvar;
1384              
1385             # Totally different outrefs format than ARRAY
1386             sub _outrefs
1387 6775     6775   9251 {
1388 6775         9952 my $self = shift;
1389             my ( $match, $no_desc ) = @_;
1390 6775         12428  
1391             my $padcv = $self->padcv;
1392 6775         13727  
1393             my @svs = $self->elems;
1394 6775         11570  
1395             my @outrefs;
1396 6775 100 66     25509  
1397 6272 100       15127 if( $match & STRENGTH_STRONG and my $argsav = $svs[0] ) {
1398             push @outrefs, $no_desc ? ( strong => $argsav ) :
1399             Devel::MAT::SV::Reference( "the " . Devel::MAT::Cmd->format_note( '@_', 1 ) . " av", strong => $argsav );
1400             }
1401 6775         14368  
1402 51831 100       102984 foreach my $idx ( 1 .. $#svs ) {
1403             my $sv = $svs[$idx] or next;
1404 48981         57308  
1405 48981 100       74418 my $name;
1406 242         408 if( !$no_desc ) {
1407 242 100       565 my $padname = $padcv->padname( $idx );
1408 242 100       950 $name = $padname ? $padname->name : undef;
1409 70         168 if( $name ) {
1410             $name = "the lexical " . Devel::MAT::Cmd->format_note( $name, 1 );
1411             }
1412 172         296 else {
1413             $name = "pad temporary $idx";
1414             }
1415             }
1416 48981 50       78076  
1417 48981 100       82050 if( $match & STRENGTH_STRONG ) {
1418             push @outrefs, $no_desc ? ( strong => $sv ) :
1419             Devel::MAT::SV::Reference( $name, strong => $sv );
1420 48981 50 66     107620 }
      66        
      66        
1421 423 100       1421 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1422             push @outrefs, $no_desc ? ( indirect => $rv ) :
1423             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1424             }
1425             }
1426 6775         28834  
1427             return @outrefs;
1428             }
1429              
1430 9     9   83 package Devel::MAT::SV::HASH 0.51;
  9         60  
  9         905  
1431             use base qw( Devel::MAT::SV );
1432 9     9   60 __PACKAGE__->register_type( 5 );
  9         41  
  9         830  
1433 9     9   60 use constant $CONSTANTS;
  9         19  
  9         9675  
1434             use constant basetype => "HV";
1435              
1436             =head1 Devel::MAT::SV::HASH
1437              
1438             Represents a hash; an SV of type C. The C
1439             subclass is used to represent hashes that are used as stashes.
1440              
1441             =cut
1442              
1443             sub load
1444 10011     10011   17057 {
1445 10011         17888 my $self = shift;
1446 10011         20681 my ( $header, $ptrs, $strs ) = @_;
1447             my $df = $self->df;
1448 10011         28418  
1449             ( my $n ) =
1450             unpack "$df->{uint_fmt} a*", $header;
1451 10011         17546  
1452 10011         24637 my %values_at;
1453 169593         309740 foreach ( 1 .. $n ) {
1454 169593         312492 my $key = $df->_read_str;
1455             $values_at{$key} = $df->_read_ptr;
1456             }
1457              
1458 10011         217751 $self->_set_hash_fields(
1459             $ptrs->[0], # BACKREFS
1460             \%values_at,
1461             );
1462              
1463             }
1464              
1465             # Back-compat. for loading old .pmat files that didn't store AvREAL
1466             sub _fixup
1467 10011     10011   13576 {
1468             my $self = shift;
1469 10011 100       16352  
1470 2264 100       9565 if( my $backrefs = $self->backrefs ) {
1471             $backrefs->_set_backrefs( 1 ) if $backrefs->type eq "ARRAY";
1472             }
1473             }
1474              
1475             sub _more_saved
1476 1     1   4 {
1477 1         3 my $self = shift;
1478             my ( $keyaddr, $valaddr ) = @_;
1479 1         2  
  1         7  
1480             push @{ $self->{saved} }, [ $keyaddr, $valaddr ];
1481             }
1482              
1483             sub symname
1484 3     3   8 {
1485 3 50       29 my $self = shift;
1486 3         19 return unless my $glob_at = $self->glob_at;
1487             return $mksymname->( '%', $self->df->sv_at( $glob_at ) );
1488             }
1489              
1490             # HVs have a backrefs field directly, rather than using magic
1491             sub backrefs
1492 23976     23976   40135 {
1493 23976         97093 my $self = shift;
1494             return $self->df->sv_at( $self->backrefs_at );
1495             }
1496              
1497             =head2 keys
1498              
1499             @keys = $hv->keys
1500              
1501             Returns the set of keys present in the hash, as plain perl strings, in no
1502             particular order.
1503              
1504             =cut
1505              
1506             # XS accessor
1507              
1508             =head2 value
1509              
1510             $sv = $hv->value( $key )
1511              
1512             Returns the SV associated with the given key
1513              
1514             =cut
1515              
1516             sub value
1517 7861     7861   12092 {
1518 7861         12496 my $self = shift;
1519 7861         26433 my ( $key ) = @_;
1520             return $self->df->sv_at( $self->value_at( $key ) );
1521             }
1522              
1523             =head2 values
1524              
1525             @svs = $hv->values
1526              
1527             Returns all of the SVs stored as values, in no particular order (though, in an
1528             order corresponding to the order returned by C).
1529              
1530             =cut
1531              
1532             sub values
1533 534     534   726 {
1534 534 50       976 my $self = shift;
1535             return $self->n_values if !wantarray;
1536 534         1315  
1537 534         1446 my $df = $self->df;
  3904         6590  
1538             return map { $df->sv_at( $_ ) } $self->values_at;
1539             }
1540              
1541             sub desc
1542 2860     2860   10967 {
1543 2860 100       11274 my $self = shift;
1544 2860         8986 my $named = $self->{name} ? " named $self->{name}" : "";
1545             return "HASH(" . $self->n_values . ")";
1546             }
1547              
1548             sub _outrefs
1549 7957     7957   16078 {
1550 7957         17018 my $self = shift;
1551             my ( $match, $no_desc ) = @_;
1552 7957         28058  
1553             my $df = $self->df;
1554 7957         13161  
1555             my @outrefs;
1556 7957 100       28043  
1557             if( my $backrefs = $self->backrefs ) {
1558             # backrefs are optimised so if there's only one backref, it is stored
1559 5684 100       30664 # in the backrefs slot directly
1560 5674 50       15646 if( $backrefs->type eq "ARRAY" ) {
1561 5674 100       22247 if( $match & STRENGTH_STRONG ) {
1562             push @outrefs, $no_desc ? ( strong => $backrefs ) :
1563             Devel::MAT::SV::Reference( "the backrefs list", strong => $backrefs );
1564             }
1565 5674 50       41931  
1566 5674         15734 if( $match & STRENGTH_INDIRECT ) {
1567 5346616 100       27366934 foreach my $sv ( $self->backrefs->elems ) {
1568             push @outrefs, $no_desc ? ( indirect => $sv ) :
1569             Devel::MAT::SV::Reference( "a backref", indirect => $sv );
1570             }
1571             }
1572             }
1573 10 50       35 else {
1574 10 50       45 if( $match & STRENGTH_WEAK ) {
1575             push @outrefs, $no_desc ? ( weak => $backrefs ) :
1576             Devel::MAT::SV::Reference( "a backref", weak => $backrefs );
1577             }
1578             }
1579             }
1580 7957         947820  
1581 2291583 100       9739736 foreach my $key ( $self->keys ) {
1582 2267552 100       5508896 my $sv = $df->sv_at( $self->value_at( $key ) ) or next;
1583             my $name = $no_desc ? undef :
1584             "value " . Devel::MAT::Cmd->format_value( $key, key => 1 );
1585 2267552 50       4714850  
1586 2267552 100       4685115 if( $match & STRENGTH_STRONG ) {
1587             push @outrefs, $no_desc ? ( strong => $sv ) :
1588             Devel::MAT::SV::Reference( $name, strong => $sv );
1589 2267552 50 66     17503399 }
      66        
      66        
1590 4679 100       12298 if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
1591             push @outrefs, $no_desc ? ( indirect => $sv ) :
1592             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
1593             }
1594             }
1595 7957         238787  
  7957         39189  
1596 1         6 foreach my $saved ( @{ $self->{saved} } ) {
1597 1         7 my $keysv = $self->df->sv_at( $saved->[0] );
1598             my $valsv = $self->df->sv_at( $saved->[1] );
1599 1 50       6  
1600             push @outrefs, $no_desc ? ( inferred => $keysv ) :
1601             Devel::MAT::SV::Reference( "a key for saved value",
1602 1 50       11 inferred => $keysv );
1603             push @outrefs, $no_desc ? ( inferred => $valsv ) :
1604             Devel::MAT::SV::Reference( "saved value of value " . Devel::MAT::Cmd->format_value( $keysv->pv, key => 1 ),
1605             inferred => $valsv );
1606             }
1607 7957         687586  
1608             return @outrefs;
1609             }
1610              
1611 9     9   67 package Devel::MAT::SV::STASH 0.51;
  9         19  
  9         2902  
1612             use base qw( Devel::MAT::SV::HASH );
1613 9     9   66 __PACKAGE__->register_type( 6 );
  9         22  
  9         7280  
1614             use constant $CONSTANTS;
1615              
1616             =head1 Devel::MAT::SV::STASH
1617              
1618             Represents a hash used as a stash; an SV of type C whose C
1619             is non-NULL. This is a subclass of C.
1620              
1621             =cut
1622              
1623             sub load
1624 2334     2334   4346 {
1625 2334         5569 my $self = shift;
1626 2334         5601 my ( $header, $ptrs, $strs ) = @_;
1627             my $df = $self->df;
1628 2334         3374  
  2334         5326  
1629             my ( $hash_bytes, $hash_ptrs, $hash_strs ) = @{ $df->{sv_sizes}[5] };
1630 2334         15841  
1631             $self->SUPER::load(
1632             substr( $header, 0, $hash_bytes, "" ),
1633             [ splice @$ptrs, 0, $hash_ptrs ],
1634             [ splice @$strs, 0, $hash_strs ],
1635             );
1636 2334         14019  
  2334         9954  
1637             @{$self}{qw( mro_linearall_at mro_linearcurrent_at mro_nextmethod_at mro_isa_at )} =
1638             @$ptrs;
1639 2334         9746  
1640             ( $self->{name} ) =
1641             @$strs;
1642             }
1643              
1644             =head2 mro_linear_all
1645              
1646             =head2 mro_linearcurrent
1647              
1648             =head2 mro_nextmethod
1649              
1650             =head2 mro_isa
1651              
1652             $hv = $stash->mro_linear_all
1653              
1654             $sv = $stash->mro_linearcurrent
1655              
1656             $sv = $stash->mro_nextmethod
1657              
1658             $av = $stash->mro_isa
1659              
1660             Returns the fields from the MRO structure
1661              
1662             =cut
1663 6037     6037   13969  
  6037         39683  
1664 6037     6037   21107 sub mro_linearall { my $self = shift; return $self->df->sv_at( $self->{mro_linearall_at} ) }
  6037         24471  
1665 6037     6037   13561 sub mro_linearcurrent { my $self = shift; return $self->df->sv_at( $self->{mro_linearcurrent_at} ) }
  6037         22586  
1666 6037     6037   12963 sub mro_nextmethod { my $self = shift; return $self->df->sv_at( $self->{mro_nextmethod_at} ) }
  6037         22745  
1667             sub mro_isa { my $self = shift; return $self->df->sv_at( $self->{mro_isa_at} ) }
1668              
1669             =head2 value_code
1670              
1671             $cv = $stash->value_code( $key )
1672              
1673             Returns the CODE associated with the given symbol name, if it exists, or
1674             C if not. This is roughly equivalent to
1675              
1676             $cv = $stash->value( $key )->code
1677              
1678             Except that it is aware of the direct reference to CVs that perl 5.22 will
1679             optimise for. This method should be used in preference to the above construct.
1680              
1681             =cut
1682              
1683             sub value_code
1684 1     1   315 {
1685 1         5 my $self = shift;
1686             my ( $key ) = @_;
1687 1 50       5  
1688 1 50       11 my $sv = $self->value( $key ) or return undef;
    0          
1689 1         4 if( $sv->type eq "GLOB" ) {
1690             return $sv->code;
1691             }
1692 0         0 elsif( $sv->type eq "REF" ) {
1693             return $sv->rv;
1694             }
1695 0         0  
  0         0  
1696             die "TODO: value_code on non-GLOB, non-REF ${\ $sv->desc }";
1697             }
1698              
1699             =head2 stashname
1700              
1701             $name = $stash->stashname
1702              
1703             Returns the name of the stash
1704              
1705             =cut
1706              
1707             sub stashname
1708 28     28   48 {
1709 28         206 my $self = shift;
1710             return $self->{name};
1711             }
1712              
1713             sub desc
1714 667     667   3111 {
1715 667         1432 my $self = shift;
1716 667         2805 my $desc = $self->SUPER::desc;
1717 667         1512 $desc =~ s/^HASH/STASH/;
1718             return $desc;
1719             }
1720              
1721             sub _outrefs
1722 5704     5704   13876 {
1723 5704         14613 my $self = shift;
1724             my ( $match, $no_desc ) = @_;
1725 5704         24526  
1726             my @outrefs = $self->SUPER::_outrefs( @_ );
1727 5704 50       51101  
1728 5704 50       26896 if( $match & STRENGTH_STRONG ) {
1729 0 0       0 if( my $sv = $self->mro_linearall ) {
1730             push @outrefs, $no_desc ? ( strong => $sv ) :
1731             Devel::MAT::SV::Reference( "the mro linear all HV", strong => $sv );
1732 5704 100       22716 }
1733 1958 100       8997 if( my $sv = $self->mro_linearcurrent ) {
1734             push @outrefs, $no_desc ? ( strong => $sv ) :
1735             Devel::MAT::SV::Reference( "the mro linear current", strong => $sv );
1736 5704 50       26940 }
1737 0 0       0 if( my $sv = $self->mro_nextmethod ) {
1738             push @outrefs, $no_desc ? ( strong => $sv ) :
1739             Devel::MAT::SV::Reference( "the mro next::method", strong => $sv );
1740 5704 100       16527 }
1741 1958 100       8116 if( my $sv = $self->mro_isa ) {
1742             push @outrefs, $no_desc ? ( strong => $sv ) :
1743             Devel::MAT::SV::Reference( "the mro ISA cache", strong => $sv );
1744             }
1745             }
1746 5704         431798  
1747             return @outrefs;
1748             }
1749              
1750 9     9   69 package Devel::MAT::SV::CODE 0.51;
  9         22  
  9         1092  
1751             use base qw( Devel::MAT::SV );
1752 9     9   64 __PACKAGE__->register_type( 7 );
  9         18  
  9         1011  
1753 9     9   70 use constant $CONSTANTS;
  9         29  
  9         531  
1754             use constant basetype => "CV";
1755 9     9   61  
  9         15  
  9         668  
1756             use Carp;
1757 9     9   62  
  9         182  
  9         683  
1758             use List::Util 1.44 qw( uniq );
1759 9     9   74  
  9         145  
  9         52  
1760             use Struct::Dumb 0.07 qw( struct );
1761             struct Padname => [qw( name ourstash flags fieldix fieldstash_at )];
1762 9     9   770 {
  9         40  
  9         28134  
1763 0     0   0 no strict 'refs';
1764 0     0   0 *{__PACKAGE__."::Padname::is_outer"} = sub { shift->flags & 0x01 };
1765 0     0   0 *{__PACKAGE__."::Padname::is_state"} = sub { shift->flags & 0x02 };
1766 0     0   0 *{__PACKAGE__."::Padname::is_lvalue"} = sub { shift->flags & 0x04 };
1767 0     0   0 *{__PACKAGE__."::Padname::is_typed"} = sub { shift->flags & 0x08 };
1768             *{__PACKAGE__."::Padname::is_our"} = sub { shift->flags & 0x10 };
1769              
1770 0     0   0 # Internal flags, not appearing in the file itself
1771             *{__PACKAGE__."::Padname::is_field"} = sub { shift->flags & 0x100 };
1772             }
1773              
1774             =head1 Devel::MAT::SV::CODE
1775              
1776             Represents a function or closure; an SV of type C.
1777              
1778             =cut
1779              
1780             sub load
1781 43407     43407   70706 {
1782 43407         72534 my $self = shift;
1783 43407         89263 my ( $header, $ptrs, $strs ) = @_;
1784             my $df = $self->df;
1785 43407         146330  
1786             my ( $line, $flags, $oproot, $depth ) =
1787             unpack "$df->{uint_fmt} C $df->{ptr_fmt} $df->{u32_fmt}", $header;
1788 43407 50       93030  
1789             defined $depth or $depth = -1;
1790              
1791 43407         71281 $self->_set_code_fields( $line, $flags, $oproot, $depth,
1792 43407         65744 @{$ptrs}[0, 2..4], # STASH, OUTSIDE, PADLIST, CONSTVAL
  43407         165814  
1793             @{$strs}[0, 1], # FILE, NAME
1794 43407         122343 );
1795             $self->_set_glob_at( $ptrs->[1] );
1796              
1797 43407 50       140517 # After perl 5.20 individual padname structs are no longer arena-allocated
1798             $self->{padnames} = [] if $df->{perlver} > ( ( 5 << 24 ) | ( 20 << 16 ) | 0xffff );
1799 43407         104889  
1800             while( my $type = $df->_read_u8 ) {
1801 117277         135843 match( $type : == ) {
  117277         238211  
1802 0         0 case( 1 ) { push @{ $self->{consts_at} }, $df->_read_ptr }
  0         0  
1803 43544         51621 case( 2 ) { push @{ $self->{constix} }, $df->_read_uint }
  43544         99147  
1804 0         0 case( 3 ) { push @{ $self->{gvs_at} }, $df->_read_ptr }
  0         0  
1805 172901         308234 case( 4 ) { push @{ $self->{gvix} }, $df->_read_uint }
1806 172901         267518 case( 5 ) { my $padix = $df->_read_uint;
1807             $self->{padnames}[$padix] = _load_padname( $df ); }
1808 0         0 case( 6 ) { # ignore - used to be padsvs_at
  0         0  
  0         0  
1809 23576         47108 $df->_read_uint; $df->_read_uint; $df->_read_ptr; }
1810 23646         43751 case( 7 ) { $self->_set_padnames_at( $df->_read_ptr ); }
1811 23646         46742 case( 8 ) { my $depth = $df->_read_uint;
1812 34116         74408 $self->{pads_at}[$depth] = $df->_read_ptr; }
1813 34116         64752 case( 9 ) { my $padname = $self->{padnames}[ $df->_read_uint ];
1814 0         0 $padname->flags = $df->_read_u8; }
1815 0         0 case( 10 ) { my $padname = $self->{padnames}[ $df->_read_uint ];
1816 0         0 $padname->flags |= 0x100;
1817 0         0 $padname->fieldix = $df->_read_uint;
1818 415060 100       1018135 $padname->fieldstash_at = $df->_read_ptr; }
    50          
    100          
    50          
    100          
    50          
    100          
    100          
    50          
    0          
1819 0         0 default {
1820             die "TODO: unhandled CODEx type $type";
1821             }
1822             }
1823             }
1824             }
1825              
1826             sub _load_padname
1827 172901     172901   246377 {
1828             my ( $df ) = @_;
1829 172901         307423  
1830             return Padname( $df->_read_str, $df->_read_ptr, 0, 0, 0 );
1831             }
1832              
1833             sub _fixup
1834 43407     43407   56325 {
1835             my $self = shift;
1836 43407         97505  
1837             my $df = $self->df;
1838 43407         65099  
1839 43407 50       73925 my $padlist = $self->padlist;
1840 0         0 if( $padlist ) {
1841 0         0 bless $padlist, "Devel::MAT::SV::PADLIST";
1842             $padlist->_set_padcv_at( $self->addr );
1843             }
1844 43407         54939  
1845             my $padnames;
1846             my @pads;
1847              
1848 43407 50       72043 # 5.18.0 onwards has a totally different padlist arrangement
    0          
1849 43407         66906 if( $df->{perlver} >= ( ( 5 << 24 ) | ( 18 << 16 ) ) ) {
1850             $padnames = $self->padnames_av;
1851 43407         56643  
  47222         78344  
  43407         126405  
1852 43407         64864 @pads = map { $df->sv_at( $_ ) } @{ $self->{pads_at} };
1853             shift @pads; # always zero
1854             }
1855             elsif( $padlist ) {
1856             # PADLIST[0] stores the names of the lexicals
1857 0         0 # The rest stores the actual pads
1858 0         0 ( $padnames, @pads ) = $padlist->elems;
1859             $self->_set_padnames_at( $padnames->addr );
1860             }
1861 43407 50       70100  
1862 0         0 if( $padnames ) {
1863 0         0 bless $padnames, "Devel::MAT::SV::PADNAMES";
1864             $padnames->_set_padcv_at( $self->addr );
1865 0         0  
1866             $self->{padnames} = \my @padnames;
1867 0         0  
1868 0 0       0 foreach my $padix ( 1 .. $padnames->elems - 1 ) {
1869 0 0       0 my $padnamesv = $padnames->elem( $padix ) or next;
1870             $padnamesv->immortal and next; # UNDEF
1871 0         0  
1872             $padnames[$padix] = Padname( $padnamesv->pv, $padnamesv->ourstash, 0, 0, 0 );
1873             }
1874             }
1875 43407         63104  
1876 23646 100       42075 foreach my $pad ( @pads ) {
1877             next unless $pad;
1878 23639         34507  
1879 23639         65553 bless $pad, "Devel::MAT::SV::PAD";
1880             $pad->_set_padcv_at( $self->addr );
1881             }
1882 43407         75215  
1883             $self->{pads} = \@pads;
1884              
1885 43407 50       81728 # Under ithreads, constants and captured GVs are actually stored in the first padlist
1886 0         0 if( $df->ithreads ) {
1887             my $pad0 = $pads[0];
1888 0         0  
1889 0 0       0 foreach my $type (qw( const gv )) {
1890 0   0     0 my $idxes = $self->{"${type}ix"} or next;
1891             my $svs_at = $self->{"${type}s_at"} ||= [];
1892 0         0  
  0         0  
1893 0 0       0 @$svs_at = map { my $e = $pad0->elem($_);
1894             $e ? $e->addr : undef } uniq @$idxes;
1895             }
1896             }
1897 43407 100 66     139988  
1898 3286 50       10530 if( $self->is_cloned and my $oproot = $self->oproot ) {
1899 3286         10267 if( my $protosub = $df->{protosubs_by_oproot}{$oproot} ) {
1900             $self->_set_protosub_at( $protosub->addr );
1901             }
1902             }
1903             }
1904              
1905             =head2 stash
1906              
1907             =head2 glob
1908              
1909             =head2 file
1910              
1911             =head2 line
1912              
1913             =head2 scope
1914              
1915             =head2 padlist
1916              
1917             =head2 constval
1918              
1919             =head2 oproot
1920              
1921             =head2 depth
1922              
1923             $stash = $cv->stash
1924              
1925             $gv = $cv->glob
1926              
1927             $filename = $cv->file
1928              
1929             $line = $cv->line
1930              
1931             $scope_cv = $cv->scope
1932              
1933             $av = $cv->padlist
1934              
1935             $sv = $cv->constval
1936              
1937             $addr = $cv->oproot
1938              
1939             $depth = $cv->depth
1940              
1941             Returns the stash, glob, filename, line number, scope, padlist, constant value,
1942             oproot or depth of the code.
1943              
1944             =cut
1945 15793     15793   24999  
  15793         53515  
1946 15816     15816   23350 sub stash { my $self = shift; return $self->df->sv_at( $self->stash_at ) }
  15816         48210  
1947             sub glob { my $self = shift; return $self->df->sv_at( $self->glob_at ) }
1948 21219     21219   30294 # XS accessors: file, line
  21219         61501  
1949 64626     64626   81669 sub scope { my $self = shift; return $self->df->sv_at( $self->outside_at ) }
  64626         206541  
1950 33620     33620   46740 sub padlist { my $self = shift; return $self->df->sv_at( $self->padlist_at ) }
  33620         102606  
1951             sub constval { my $self = shift; return $self->df->sv_at( $self->constval_at ) }
1952             # XS accessors: oproot, depth
1953              
1954             =head2 location
1955              
1956             $location = $cv->location
1957              
1958             Returns C if the line is defined, or C if not.
1959              
1960             =cut
1961              
1962             sub location
1963 0     0   0 {
1964 0         0 my $self = shift;
1965 0         0 my $line = $self->line;
1966             my $file = $self->file;
1967 0 0       0 # line 0 is invalid
1968             return $line ? "$file line $line" : $file;
1969             }
1970              
1971             =head2 is_clone
1972              
1973             =head2 is_cloned
1974              
1975             =head2 is_xsub
1976              
1977             =head2 is_weakoutside
1978              
1979             =head2 is_cvgv_rc
1980              
1981             =head2 is_lexical
1982              
1983             $clone = $cv->is_clone
1984              
1985             $cloned = $cv->is_cloned
1986              
1987             $xsub = $cv->is_xsub
1988              
1989             $weak = $cv->is_weakoutside
1990              
1991             $rc = $cv->is_cvgv_rc
1992              
1993             $lexical = $cv->is_lexical
1994              
1995             Returns the C, C, C, C,
1996             C and C flags.
1997              
1998             =cut
1999              
2000             # XS accessors
2001              
2002             =head2 protosub
2003              
2004             $protosub = $cv->protosub
2005              
2006             Returns the protosub CV, if known, for a closure CV.
2007              
2008             =cut
2009 15794     15794   23726  
  15794         48600  
2010             sub protosub { my $self = shift; return $self->df->sv_at( $self->protosub_at ); }
2011              
2012             =head2 constants
2013              
2014             @svs = $cv->constants
2015              
2016             Returns a list of the SVs used as constants or method names in the code. On
2017             ithreads perl the constants are part of the padlist structure so this list is
2018             constructed from parts of the padlist at loading time.
2019              
2020             =cut
2021              
2022             sub constants
2023 21220     21220   28351 {
2024 21220         37761 my $self = shift;
2025 21220 100       28063 my $df = $self->df;
  47636         81636  
  21220         95928  
2026             return map { $df->sv_at($_) } @{ $self->{consts_at} || [] };
2027             }
2028              
2029             =head2 globrefs
2030              
2031             @svs = $cv->globrefs
2032              
2033             Returns a list of the SVs used as GLOB references in the code. On ithreads
2034             perl the constants are part of the padlist structure so this list is
2035             constructed from parts of the padlist at loading time.
2036              
2037             =cut
2038              
2039             sub globrefs
2040 21219     21219   30051 {
2041 21219         38521 my $self = shift;
2042 21219         29659 my $df = $self->df;
  18367         33156  
  21219         69791  
2043             return map { $df->sv_at($_) } @{ $self->{gvs_at} };
2044             }
2045 0 0   0   0  
  0         0  
2046             sub stashname { my $self = shift; return $self->stash ? $self->stash->stashname : undef }
2047              
2048             sub symname
2049 23     23   55 {
2050             my $self = shift;
2051              
2052 23 50       98 # CvLEXICALs or CVs with non-reified CvGVs may still have a hekname
    100          
2053 0         0 if( defined( my $hekname = $self->hekname ) ) {
2054 0         0 my $stashname = $self->stashname;
2055 0         0 $stashname =~ s/^main:://;
2056             return '&' . $stashname . "::" . $hekname;
2057             }
2058 22         59 elsif( my $glob = $self->glob ) {
2059             return '&' . $glob->stashname;
2060             }
2061 1         5  
2062             return undef;
2063             }
2064              
2065             =head2 padname
2066              
2067             $padname = $cv->padname( $padix )
2068              
2069             Returns the name of the $padix'th lexical variable, or C if it doesn't
2070             have a name.
2071              
2072             The returned padname is a structure of the following fields:
2073              
2074             $name = $padname->name
2075              
2076             $bool = $padname->is_outer
2077             $bool = $padname->is_state
2078             $bool = $padname->is_lvalue
2079             $bool = $padname->is_typed
2080             $bool = $padname->is_our
2081             $bool = $padname->is_field
2082              
2083             =cut
2084              
2085             sub padname
2086 243     243   343 {
2087 243         379 my $self = shift;
2088             my ( $padix ) = @_;
2089 243         450  
2090             return $self->{padnames}[$padix];
2091             }
2092              
2093             =head2 padix_from_padname
2094              
2095             $padix = $cv->padix_from_padname( $padname )
2096              
2097             Returns the index of the first lexical variable with the given pad name, or
2098             C if one does not exist.
2099              
2100             =cut
2101              
2102             sub padix_from_padname
2103 5     5   670 {
2104 5         13 my $self = shift;
2105             my ( $padname ) = @_;
2106 5         9  
2107             my $padnames = $self->{padnames};
2108 5         19  
2109 29         102 foreach my $padix ( 1 .. $#$padnames ) {
2110             my $thisname;
2111 29 100 66     77  
      100        
2112             return $padix if defined $padnames->[$padix] and
2113             defined( $thisname = $padnames->[$padix]->name ) and
2114             $thisname eq $padname;
2115             }
2116 0         0  
2117             return undef;
2118             }
2119              
2120             =head2 max_padix
2121              
2122             $max_padix = $cv->max_padix
2123              
2124             Returns the maximum valid pad index.
2125              
2126             This is typically used to create a list of potential pad indexes, such as
2127              
2128             0 .. $cv->max_padix
2129              
2130             Note that since pad slots may contain things other than lexical variables, not
2131             every pad slot between 0 and this index will necessarily contain a lexical
2132             variable or have a pad name.
2133              
2134             =cut
2135              
2136             sub max_padix
2137 1     1   4 {
2138 1         2 my $self = shift;
  1         11  
2139             return $#{ $self->{padnames} };
2140             }
2141              
2142             =head2 padnames_av
2143              
2144             $padnames_av = $cv->padnames_av
2145              
2146             Returns the AV reference directly which stores the pad names.
2147              
2148             After perl version 5.20, this is no longer used directly and will return
2149             C. The individual pad names themselves can still be found via the
2150             C method.
2151              
2152             =cut
2153              
2154             sub padnames_av
2155 64626     64626   86105 {
2156             my $self = shift;
2157 64626   50     190972  
      0        
2158 0         0 return $self->df->sv_at( $self->padnames_at or return undef )
2159             // croak "${\ $self->desc } PADNAMES is not accessible";
2160             }
2161              
2162             =head2 pads
2163              
2164             @pads = $cv->pads
2165              
2166             Returns a list of the actual pad AVs.
2167              
2168             =cut
2169              
2170             sub pads
2171 5426     5426   6822 {
2172 5426 50       12715 my $self = shift;
  5426         12763  
2173             return $self->{pads} ? @{ $self->{pads} } : ();
2174             }
2175              
2176             =head2 pad
2177              
2178             $pad = $cv->pad( $depth )
2179              
2180             Returns the PAD at the given depth (given by 1-based index).
2181              
2182             =cut
2183              
2184             sub pad
2185 7     7   992 {
2186 7         16 my $self = shift;
2187 7 50       59 my ( $depth ) = @_;
2188             return $self->{pads} ? $self->{pads}[$depth-1] : undef;
2189             }
2190              
2191             =head2 maybe_lexvar
2192              
2193             $sv = $cv->maybe_lexvar( $padname, $depth )
2194              
2195             I
2196              
2197             Returns the SV on the PAD associated with the given padname, at the
2198             optionally-given depth (1-based index). If I<$depth> is not provided, the
2199             topmost live PAD will be used. If no variable exists of the given name returns
2200             C.
2201              
2202             Used to be called C.
2203              
2204             =cut
2205              
2206             sub maybe_lexvar
2207 3     3   128 {
2208 3         102 my $self = shift;
2209             my ( $padname, $depth ) = @_;
2210 3   66     28  
2211 3 50       8 $depth //= $self->depth;
2212             $depth or croak "Cannot fetch current pad of a non-live CODE";
2213 3         13  
2214             return $self->pad( $depth )->maybe_lexvar( $padname );
2215             }
2216              
2217             *lexvar = \&maybe_lexvar;
2218              
2219             sub desc
2220 12401     12401   53533 {
2221             my $self = shift;
2222 12401         15547  
2223 12401 100       34965 my @flags;
2224 12401 100       20330 push @flags, "PP" if $self->oproot;
2225 12401 100       29170 push @flags, "CONST" if $self->constval;
2226             push @flags, "XS" if $self->is_xsub;
2227 12401 100       23603  
2228 12401 100       22859 push @flags, "closure" if $self->is_cloned;
2229             push @flags, "proto" if $self->is_clone;
2230 12401         17638  
2231 12401         31113 local $" = ",";
2232             return "CODE(@flags)";
2233             }
2234              
2235             sub _outrefs
2236 15793     15793   23054 {
2237 15793         26575 my $self = shift;
2238             my ( $match, $no_desc ) = @_;
2239 15793         51247  
2240             my $pads = $self->{pads};
2241 15793 50       37121  
2242             my $maxdepth = $pads ? scalar @$pads : 0;
2243 15793         34142  
2244             my $have_padlist = defined $self->padlist;
2245 15793         25490  
2246             my @outrefs;
2247 15793         36089  
2248 15793 100 66     54090 my $is_weakoutside = $self->is_weakoutside;
    100          
2249 6489 100       12603 if( $match & ( $is_weakoutside ? STRENGTH_WEAK : STRENGTH_STRONG ) and my $scope = $self->scope ) {
2250 6489 100       13628 my $strength = $is_weakoutside ? "weak" : "strong";
2251             push @outrefs, $no_desc ? ( $strength => $scope ) :
2252             Devel::MAT::SV::Reference( "the scope", $strength => $scope );
2253             }
2254 15793 100 66     54063  
2255 13421 100       35982 if( $match & STRENGTH_WEAK and my $stash = $self->stash ) {
2256             push @outrefs, $no_desc ? ( weak => $stash ) :
2257             Devel::MAT::SV::Reference( "the stash", weak => $stash );
2258             }
2259 15793         50561  
2260 15793 100 66     49312 my $is_strong_gv = $self->is_cvgv_rc;
    100          
2261 15492 100       31449 if( $match & ( $is_strong_gv ? STRENGTH_STRONG : STRENGTH_WEAK ) and my $glob = $self->glob ) {
2262 15492 100       40724 my $strength = $is_strong_gv ? "strong" : "weak";
2263             push @outrefs, $no_desc ? ( $strength => $glob ) :
2264             Devel::MAT::SV::Reference( "the glob", $strength => $glob );
2265             }
2266 15793 100 66     66889  
2267 6798 100       20277 if( $match & STRENGTH_STRONG and my $constval = $self->constval ) {
2268             push @outrefs, $no_desc ? ( strong => $constval ) :
2269             Devel::MAT::SV::Reference( "the constant value", strong => $constval );
2270             }
2271 15793 100 66     58405  
2272 941 100       2527 if( $match & STRENGTH_INFERRED and my $protosub = $self->protosub ) {
2273             push @outrefs, $no_desc ? ( inferred => $protosub ) :
2274             Devel::MAT::SV::Reference( "the protosub", inferred => $protosub );
2275             }
2276              
2277             # Under ithreads, constants and captured GVs are actually stored in the
2278 15793         48359 # first padlist, so they're only here.
2279             my $ithreads = $self->df->ithreads;
2280 15793 50       43677  
    50          
2281 15793 50       30208 if( $match & ( $ithreads ? STRENGTH_INDIRECT : STRENGTH_STRONG ) ) {
2282             my $strength = $ithreads ? "indirect" : "strong";
2283 15793         29068  
2284 33732 50       63668 foreach my $sv ( $self->constants ) {
2285 33732 100       61752 $sv or next;
2286             push @outrefs, $no_desc ? ( $strength => $sv ) :
2287             Devel::MAT::SV::Reference( "a constant", $strength => $sv );
2288 15793         35430 }
2289 12532 50       23414 foreach my $sv ( $self->globrefs ) {
2290 12532 100       24517 $sv or next;
2291             push @outrefs, $no_desc ? ( $strength => $sv ) :
2292             Devel::MAT::SV::Reference( "a referenced glob", $strength => $sv );
2293             }
2294             }
2295 15793 50 33     56350  
2296 0 0       0 if( $match & STRENGTH_STRONG and $have_padlist ) {
2297             push @outrefs, $no_desc ? ( strong => $self->padlist ) :
2298             Devel::MAT::SV::Reference( "the padlist", strong => $self->padlist );
2299             }
2300              
2301             # If we have a PADLIST then its contents are indirect; if not then they
2302 15793 50       38057 # are direct strong
    50          
2303 15793 50       27690 if( $match & ( $have_padlist ? STRENGTH_INDIRECT : STRENGTH_STRONG ) ) {
2304             my $strength = $have_padlist ? "indirect" : "strong";
2305 15793 50       30212  
2306 0 0       0 if( my $padnames_av = $self->padnames_av ) {
2307             push @outrefs, $no_desc ? ( $strength => $padnames_av ) :
2308             Devel::MAT::SV::Reference( "the padnames", $strength => $padnames_av );
2309             }
2310 15793         38200  
2311 6806 100       23398 foreach my $depth ( 1 .. $maxdepth ) {
2312             my $pad = $pads->[$depth-1] or next;
2313 6804 100       16754  
2314             push @outrefs, $no_desc ? ( $strength => $pad ) :
2315             Devel::MAT::SV::Reference( "pad at depth $depth", $strength => $pad );
2316             }
2317             }
2318 15793         60918  
2319             return @outrefs;
2320             }
2321              
2322 9     9   98 package Devel::MAT::SV::IO 0.51;
  9         35  
  9         1051  
2323             use base qw( Devel::MAT::SV );
2324 9     9   66 __PACKAGE__->register_type( 8 );
  9         18  
  9         874  
2325 9     9   81 use constant $CONSTANTS;
  9         18  
  9         5299  
2326             use constant basetype => "IO";
2327              
2328             =head1 Devel::MAT::SV::IO
2329              
2330             Represents an IO handle; an SV type of C.
2331              
2332             =cut
2333              
2334             sub load
2335 126     126   283 {
2336 126         323 my $self = shift;
2337 126         2415 my ( $header, $ptrs, $strs ) = @_;
2338             my $df = $self->df;
2339 126         412  
  126         531  
2340             @{$self}{qw( ifileno ofileno )} =
2341             unpack "$df->{uint_fmt}2", $header;
2342              
2343 126   66     307 defined $_ and $_ == $df->{minus_1} and
  126   100     1070  
2344             $_ = -1 for @{$self}{qw( ifileno ofileno )};
2345 126         369  
  126         577  
2346             @{$self}{qw( topgv_at formatgv_at bottomgv_at )} =
2347             @$ptrs;
2348             }
2349              
2350             =head2 ifileno
2351              
2352             =head2 ofileno
2353              
2354             $ifileno = $io->ifileno
2355              
2356             $ofileno = $io->ofileno
2357              
2358             Returns the input or output file numbers.
2359              
2360             =cut
2361 0     0   0  
  0         0  
2362 1     1   17 sub ifileno { my $self = shift; return $self->{ifileno} }
  1         8  
2363             sub ofileno { my $self = shift; return $self->{ofileno} }
2364 36     36   115  
  36         202  
2365 36     36   88 sub topgv { my $self = shift; $self->df->sv_at( $self->{topgv_at} ) }
  36         140  
2366 36     36   57 sub formatgv { my $self = shift; $self->df->sv_at( $self->{formatgv_at} ) }
  36         138  
2367             sub bottomgv { my $self = shift; $self->df->sv_at( $self->{bottomgv_at} ) }
2368 36     36   271  
2369             sub desc { "IO()" }
2370              
2371             sub _outrefs
2372 36     36   84 {
2373 36         99 my $self = shift;
2374             my ( $match, $no_desc ) = @_;
2375 36         68  
2376             my @outrefs;
2377 36 50       135  
2378 36 50       147 if( $match & STRENGTH_STRONG ) {
2379 0 0       0 if( my $gv = $self->topgv ) {
2380             push @outrefs, $no_desc ? ( strong => $gv ) :
2381             Devel::MAT::SV::Reference( "the top GV", strong => $gv );
2382 36 50       158 }
2383 0 0       0 if( my $gv = $self->formatgv ) {
2384             push @outrefs, $no_desc ? ( strong => $gv ) :
2385             Devel::MAT::SV::Reference( "the format GV", strong => $gv );
2386 36 50       176 }
2387 0 0       0 if( my $gv = $self->bottomgv ) {
2388             push @outrefs, $no_desc ? ( strong => $gv ) :
2389             Devel::MAT::SV::Reference( "the bottom GV", strong => $gv );
2390             }
2391             }
2392 36         91  
2393             return @outrefs;
2394             }
2395              
2396 9     9   76 package Devel::MAT::SV::LVALUE 0.51;
  9         24  
  9         1260  
2397             use base qw( Devel::MAT::SV );
2398 9     9   72 __PACKAGE__->register_type( 9 );
  9         38  
  9         853  
2399 9     9   60 use constant $CONSTANTS;
  9         41  
  9         3665  
2400             use constant basetype => "LV";
2401              
2402             sub load
2403 1     1   3 {
2404 1         4 my $self = shift;
2405 1         8 my ( $header, $ptrs, $strs ) = @_;
2406             my $df = $self->df;
2407 1         12  
2408             ( $self->{type}, $self->{off}, $self->{len} ) =
2409             unpack "a1 $df->{uint_fmt}2", $header;
2410 1         6  
2411             ( $self->{targ_at} ) =
2412             @$ptrs;
2413             }
2414 1     1   3  
  1         6  
2415 0     0   0 sub lvtype { my $self = shift; return $self->{type} }
  0         0  
2416 0     0   0 sub off { my $self = shift; return $self->{off} }
  0         0  
2417 0     0   0 sub len { my $self = shift; return $self->{len} }
  0         0  
2418             sub target { my $self = shift; return $self->df->sv_at( $self->{targ_at} ) }
2419 0     0   0  
2420             sub desc { "LVALUE()" }
2421              
2422             sub _outrefs
2423 0     0   0 {
2424 0         0 my $self = shift;
2425             my ( $match, $no_desc ) = @_;
2426 0         0  
2427             my @outrefs;
2428 0 0 0     0  
2429 0 0       0 if( $match & STRENGTH_STRONG and my $sv = $self->target ) {
2430             push @outrefs, $no_desc ? ( strong => $sv ) :
2431             Devel::MAT::SV::Reference( "the target", strong => $sv );
2432             }
2433 0         0  
2434             return @outrefs;
2435             }
2436              
2437 9     9   68 package Devel::MAT::SV::REGEXP 0.51;
  9         17  
  9         871  
2438 9     9   74 use base qw( Devel::MAT::SV );
  9         18  
  9         1186  
2439             use constant basetype => "REGEXP";
2440             __PACKAGE__->register_type( 10 );
2441       5009      
2442             sub load {}
2443 1429     1429   7227  
2444             sub desc { "REGEXP()" }
2445 1432     1432   2339  
2446             sub _outrefs { () }
2447              
2448 9     9   93 package Devel::MAT::SV::FORMAT 0.51;
  9         20  
  9         925  
2449 9     9   62 use base qw( Devel::MAT::SV );
  9         22  
  9         1108  
2450             use constant basetype => "PVFM";
2451             __PACKAGE__->register_type( 11 );
2452       0      
2453             sub load {}
2454 0     0   0  
2455             sub desc { "FORMAT()" }
2456 0     0   0  
2457             sub _outrefs { () }
2458              
2459 9     9   68 package Devel::MAT::SV::INVLIST 0.51;
  9         21  
  9         961  
2460 9     9   63 use base qw( Devel::MAT::SV );
  9         14  
  9         1135  
2461             use constant basetype => "INVLIST";
2462             __PACKAGE__->register_type( 12 );
2463       553      
2464             sub load {}
2465 158     158   972  
2466             sub desc { "INVLIST()" }
2467 163     163   347  
2468             sub _outrefs { () }
2469              
2470             # A hack to compress files
2471 9     9   63 package Devel::MAT::SV::_UNDEFSV 0.51;
  9         15  
  9         3665  
2472             use base qw( Devel::MAT::SV::SCALAR );
2473             __PACKAGE__->register_type( 13 );
2474              
2475             sub load
2476 159731     159731   222019 {
2477             my $self = shift;
2478 159731         244258  
2479             bless $self, "Devel::MAT::SV::SCALAR";
2480 159731         390247  
2481             $self->_set_scalar_fields( 0, 0, 0,
2482             "", 0,
2483             0,
2484             );
2485             }
2486              
2487 9     9   77 package Devel::MAT::SV::_YESSV 0.51;
  9         18  
  9         3514  
2488             use base qw( Devel::MAT::SV::BOOL );
2489             __PACKAGE__->register_type( 14 );
2490              
2491             sub load
2492 0     0     {
2493             my $self = shift;
2494 0            
2495             bless $self, "Devel::MAT::SV::BOOL";
2496 0            
2497             $self->_set_scalar_fields( 0x01, 1, 1.0,
2498             "1", 1,
2499             0,
2500             );
2501             }
2502              
2503 9     9   68 package Devel::MAT::SV::_NOSV 0.51;
  9         20  
  9         3001  
2504             use base qw( Devel::MAT::SV::BOOL );
2505             __PACKAGE__->register_type( 15 );
2506              
2507             sub load
2508 0     0     {
2509             my $self = shift;
2510 0            
2511             bless $self, "Devel::MAT::SV::BOOL";
2512 0            
2513             $self->_set_scalar_fields( 0x01, 0, 0,
2514             "", 0,
2515             0,
2516             );
2517             }
2518              
2519 9     9   75 package Devel::MAT::SV::OBJECT 0.51;
  9         18  
  9         1017  
2520             use base qw( Devel::MAT::SV );
2521 9     9   62 __PACKAGE__->register_type( 16 );
  9         23  
  9         981  
2522 9     9   62 use constant $CONSTANTS;
  9         26  
  9         6060  
2523             use constant basetype => "OBJ";
2524              
2525             =head1 Devel::MAT::SV::OBJECT
2526              
2527             Represents an object instance; an SV of type C. These are only
2528             present in files from perls with C.
2529              
2530             =cut
2531              
2532             sub load
2533 0     0     {
2534 0           my $self = shift;
2535 0           my ( $header, $ptrs, $strs ) = @_;
2536             my $df = $self->df;
2537 0            
2538             my ( $n ) =
2539             unpack "$df->{uint_fmt} a*", $header;
2540 0 0          
2541 0           my @fields_at = $n ? $df->_read_ptrs( $n ) : ();
2542             $self->_set_object_fields( \@fields_at );
2543             }
2544              
2545             =head2 fields
2546              
2547             @svs = $obj->fields
2548              
2549             Returns all the values of all the fields in a list.
2550              
2551             Note that to find the names of the fields you'll have to enquire with the
2552             class
2553              
2554             =cut
2555              
2556             sub fields
2557 0     0     {
2558             my $self = shift;
2559 0            
2560 0 0         my $n = $self->n_fields;
2561             return $n unless wantarray;
2562 0            
2563 0           my $df = $self->df;
  0            
2564             return map { $df->sv_at( $self->field_at( $_ ) ) } 0 .. $n-1;
2565             }
2566              
2567             =head2 field
2568              
2569             $sv = $obj->field( $name_or_fieldix )
2570              
2571             Returns the value of the given field; which may be specified by name or
2572             index directly.
2573              
2574             =cut
2575              
2576             sub field
2577 0     0     {
2578 0           my $self = shift;
2579             my ( $name_or_fieldix ) = @_;
2580 0            
2581 0 0         my $fieldix;
2582 0           if( $name_or_fieldix =~ m/^\d+$/ ) {
2583             $fieldix = $name_or_fieldix;
2584             }
2585 0           else {
2586             $fieldix = $self->blessed->field( $name_or_fieldix )->fieldix;
2587             }
2588 0            
2589             return $self->df->sv_at( $self->field_at( $fieldix ) );
2590             }
2591              
2592             sub desc
2593 0     0     {
2594             my $self = shift;
2595 0            
2596             return "OBJ()";
2597             }
2598              
2599             sub _outrefs
2600 0     0     {
2601 0           my $self = shift;
2602             my ( $match, $no_desc ) = @_;
2603 0            
2604             my $n = $self->n_fields;
2605 0            
2606             my @outrefs;
2607 0            
2608 0 0         foreach my $field ( $self->blessed->fields ) {
2609             my $sv = $self->field( $field->fieldix ) or next;
2610 0 0          
2611             my $name = $no_desc ? undef :
2612 0 0         "the " . Devel::MAT::Cmd->format_note( $field->name, 1 ) . " field";
2613 0 0         if( $match & STRENGTH_STRONG ) {
2614             push @outrefs, $no_desc ? ( strong => $sv ) :
2615             Devel::MAT::SV::Reference( $name, strong => $sv );
2616 0 0 0       }
      0        
      0        
2617 0 0         if( $match & STRENGTH_INDIRECT and $sv->type eq "REF" and !$sv->{magic} and my $rv = $sv->rv ) {
2618             push @outrefs, $no_desc ? ( indirect => $rv ) :
2619             Devel::MAT::SV::Reference( $name . " via RV", indirect => $rv );
2620             }
2621             }
2622 0            
2623             return @outrefs;
2624             }
2625              
2626 9     9   133 package Devel::MAT::SV::CLASS 0.51;
  9         20  
  9         2895  
2627             use base qw( Devel::MAT::SV::STASH );
2628 9     9   63 __PACKAGE__->register_type( 17 );
  9         17  
  9         702  
2629             use constant $CONSTANTS;
2630 9     9   53  
  9         19  
  9         637  
2631             use Carp;
2632 9     9   59  
  9         168  
  9         55  
2633             use Struct::Dumb 0.07 qw( readonly_struct );
2634             readonly_struct Field => [qw( fieldix name )];
2635 9     9   665  
  9         18  
  9         7429  
2636             use List::Util qw( first );
2637              
2638             =head1 Devel::MAT::SV::CLASS
2639              
2640             Represents a class; a sub-type of stash for implementing object classes. These
2641             are only present in files from perls with C.
2642              
2643             =cut
2644              
2645             sub load
2646 0     0     {
2647 0           my $self = shift;
2648 0           my ( $header, $ptrs, $strs ) = @_;
2649             my $df = $self->df;
2650 0            
  0            
2651             my ( $stash_bytes, $stash_ptrs, $stash_strs ) = @{ $df->{sv_sizes}[6] };
2652 0            
2653             $self->SUPER::load(
2654             substr( $header, 0, $stash_bytes, "" ),
2655             [ splice @$ptrs, 0, $stash_ptrs ],
2656             [ splice @$strs, 0, $stash_strs ],
2657             );
2658 0            
  0            
2659             @{$self}{qw( adjust_blocks_at )} =
2660             @$ptrs;
2661 0            
2662             while( my $type = $df->_read_u8 ) {
2663 0           match( $type : == ) {
  0            
2664 0 0         case( 1 ) { push @{ $self->{fields} }, [ $df->_read_uint, $df->_read_str ] }
2665 0           default {
2666             die "TODO: unhandled CLASSx type $type";
2667             }
2668             }
2669             }
2670             }
2671 0     0      
  0            
2672             sub adjust_blocks { my $self = shift; return $self->df->sv_at( $self->{adjust_blocks_at} ) }
2673              
2674             =head2 fields
2675              
2676             @fields = $class->fields
2677              
2678             Returns a list of the field definitions of the class, in declaration order.
2679             Each is a structure whose form is given below.
2680              
2681             =cut
2682              
2683             sub fields
2684 0     0     {
2685 0           my $self = shift;
  0            
  0            
2686             return map { Field( @$_ ) } @{ $self->{fields} };
2687             }
2688              
2689             =head2 field
2690              
2691             $field = $class->field( $name_or_fieldix )
2692              
2693             Returns the field definition of the given field; which may be specified by
2694             name or index directly. Throws an exception if none such exists.
2695              
2696             The returned field is a structure of the following fields:
2697              
2698             $fieldix = $field->fieldix
2699             $name = $field->name
2700              
2701             =head2 maybe_field
2702              
2703             $field = $class->maybe_field( $name_or_fieldix )
2704              
2705             I
2706              
2707             Similar to L but returns undef if none such exists.
2708              
2709             =cut
2710              
2711             sub maybe_field
2712 0     0     {
2713 0           my $self = shift;
2714             my ( $name_or_fieldix ) = @_;
2715 0 0          
2716 0     0     if( $name_or_fieldix =~ m/^\d+$/ ) {
  0            
2717             return first { $_->fieldix == $name_or_fieldix } $self->fields;
2718             }
2719 0     0     else {
  0            
2720             return first { $_->name eq $name_or_fieldix } $self->fields
2721             }
2722             }
2723              
2724             sub field
2725 0     0     {
2726 0   0       my $self = shift;
2727 0           return $self->maybe_field( @_ ) // do {
2728 0 0         my ( $name_or_fieldix ) = @_;
2729 0           croak "No field at index $name_or_fieldix" if $name_or_fieldix =~ m/^\d+$/;
2730             croak "No field named '$name_or_fieldix'";
2731             };
2732             }
2733              
2734             sub _outrefs
2735 0     0     {
2736 0           my $self = shift;
2737             my ( $match, $no_desc ) = @_;
2738 0            
2739             my @outrefs = $self->SUPER::_outrefs( @_ );
2740 0 0          
2741 0 0         if( $match & STRENGTH_STRONG ) {
2742 0 0         if( my $sv = $self->adjust_blocks ) {
2743             push @outrefs, $no_desc ? ( strong => $sv ) :
2744             Devel::MAT::SV::Reference( "the ADJUST blocks AV", strong => $sv );
2745             }
2746             }
2747 0            
2748             return @outrefs;
2749             }
2750              
2751             # A "SV" type that isn't really an SV, but has many of the same methods. These
2752             # aren't created by core perl, but are used by XS extensions
2753 9     9   91 package Devel::MAT::SV::C_STRUCT 0.51;
  9         33  
  9         1017  
2754             use base qw( Devel::MAT::SV );
2755 9     9   72 __PACKAGE__->register_type( 0x7F );
  9         21  
  9         981  
2756             use constant $CONSTANTS;
2757 9         755 use constant {
2758             FIELD_PTR => 0x00,
2759             FIELD_BOOL => 0x01,
2760             FIELD_U8 => 0x02,
2761             FIELD_U32 => 0x03,
2762 9     9   73 FIELD_UINT => 0x04,
  9         27  
2763 9     9   55 };
  9         16  
  9         601  
2764 9     9   61 use Carp;
  9         24  
  9         8252  
2765             use List::Util qw( first );
2766              
2767             =head1 Devel::MAT::SV::C_STRUCT
2768              
2769             Represents a C-level c type.
2770              
2771             =cut
2772              
2773             sub desc
2774 0     0     {
2775 0           my $self = shift;
2776             my $typename = $self->structtype->name;
2777 0            
2778             "C_STRUCT($typename)";
2779             }
2780              
2781             sub load
2782 0     0     {
2783 0           my $self = shift;
2784             my ( $fields ) = @_;
2785 0            
2786             my $df = $self->df;
2787 0            
2788             my @vals;
2789 0            
2790 0           foreach my $field ( @$fields ) {
2791             push @vals, my $type = $field->type;
2792 0 0 0        
    0          
    0          
    0          
2793 0           if( $type == FIELD_PTR ) {
2794             push @vals, $df->_read_ptr;
2795             }
2796 0           elsif( $type == FIELD_BOOL or $type == FIELD_U8 ) {
2797             push @vals, $df->_read_u8;
2798             }
2799 0           elsif( $type == FIELD_U32 ) {
2800             push @vals, $df->_read_u32;
2801             }
2802 0           elsif( $type == FIELD_UINT ) {
2803             push @vals, $df->_read_uint;
2804             }
2805 0           else {
2806             croak "TODO: load struct field type = $type\n";
2807             }
2808             }
2809 0            
2810             $self->_set_struct_fields( @vals );
2811             }
2812              
2813             =head2 fields
2814              
2815             @kvlist = $struct->fields
2816              
2817             Returns an even-sized name/value list of all the field values stored by the
2818             struct; each preceeded by its field type structure.
2819              
2820             =cut
2821              
2822             sub fields
2823 0     0     {
2824             my $self = shift;
2825 0            
2826             my $df = $self->df;
2827 0            
2828             my $fields = $self->structtype->fields;
2829              
2830 0           return map {
  0            
2831             my $field = $fields->[$_];
2832 0 0          
2833 0           if( $field->type == FIELD_PTR ) {
2834             $field => $df->sv_at( $self->field( $_ ) )
2835             }
2836 0           else {
2837             $field => $self->field( $_ );
2838             }
2839             } 0 .. $#$fields;
2840             }
2841              
2842             =head2 field_named
2843              
2844             $val = $struct->field_named( $name )
2845              
2846             Looks for a field whose name is exactly that given, and returns its value.
2847              
2848             Throws an exception if the struct has no such field of that name.
2849              
2850             =head2 maybe_field_named
2851              
2852             $val = $struct->maybe_field_named( $name )
2853              
2854             I
2855              
2856             As L but returns C if there is no such field.
2857              
2858             =cut
2859              
2860             sub maybe_field_named
2861 0     0     {
2862 0           my $self = shift;
2863             my ( $name ) = @_;
2864 0            
2865             my $fields = $self->structtype->fields;
2866 0 0   0      
  0            
2867             defined( my $idx = first { $fields->[$_]->name eq $name } 0 .. $#$fields )
2868             or return undef;
2869 0            
2870             my $field = $fields->[$idx];
2871 0 0          
2872 0           if( $field->type == FIELD_PTR ) {
2873             return $self->df->sv_at( $self->field( $idx ) );
2874             }
2875 0           else {
2876             return $self->field( $idx );
2877             }
2878             }
2879              
2880             sub field_named
2881 0     0     {
2882 0           my $self = shift;
2883             my ( $name ) = @_;
2884 0   0        
2885             return $self->maybe_field_named( $name ) // croak "No field named $name";
2886             }
2887              
2888             =head2 structtype
2889              
2890             $structtype = $struct->structtype
2891              
2892             Returns a metadata structure describing the type of the struct itself.
2893              
2894             Has the following named accessors
2895              
2896             =over 4
2897              
2898             =item name => STRING
2899              
2900             The name of the struct type, as given by the dumpfile.
2901              
2902             =item fields => ARRAY[ Field ]
2903              
2904             An ARRAY reference containing the definitions of each field in turn
2905              
2906             =back
2907              
2908             =cut
2909              
2910             sub structtype
2911 0     0     {
2912 0           my $self = shift;
2913             return $self->df->structtype( $self->structid );
2914             }
2915              
2916             sub _outrefs
2917 0     0     {
2918 0           my $self = shift;
2919             my ( $match, $no_desc ) = @_;
2920 0 0          
2921             return unless $match & STRENGTH_STRONG;
2922 0            
2923             my $df = $self->df;
2924 0            
2925             my @outrefs;
2926 0            
2927 0           my $fields = $self->structtype->fields;
2928 0           foreach my $idx ( 0 .. $#$fields ) {
2929 0 0         my $field = $fields->[$idx];
2930             $field->type == FIELD_PTR or next; # Is PTR
2931 0 0          
2932             my $sv = $df->sv_at( $self->field( $idx ) ) or next;
2933 0 0          
2934             push @outrefs, $no_desc ? ( strong => $sv ) :
2935             Devel::MAT::SV::Reference( $field->name, strong => $sv );
2936             }
2937 0            
2938             return @outrefs;
2939             }
2940              
2941             =head1 AUTHOR
2942              
2943             Paul Evans
2944              
2945             =cut
2946              
2947             0x55AA;