3

When looking at the Perl API, I was wondering why

  • sv_setref_iv() stores its IV argument in the IV slot,
  • sv_setref_nv() stores its NV argument in the NV slot,
  • but sv_setref_pv() stores its void * argument in the IV slot, instead of the PV slot?

I have a hunch (the CUR and LEN fields wouldn't make sense for such a variable), but I'd like to have the opinion of someone knowledgeable in XS :-)

Edward
  • 486
  • 4
  • 14

1 Answers1

6

There are many different types of scalars.

  • SvNULL isn't capable of holding any value except undef.
  • SvIV is capable of holding an IV, UV or RV.
  • SvNV is capable of holding an NV.
  • SvPV is capable of holding a PV.
  • SvPVIV is capable of holding a PV, as well as an IV, UV or RV.
  • ...

AV, HV, CV, GV are really just types of scalar too.

Note I said "capable" of holding. You can think of scalars as being objects, and the above as being classes and subclasses. Each of the above has a different structure.

Having these different types of scalars allows one to save memory.

An SvIV (the smallest scalar type capable of holding an IV) is smaller than an SvPV (the smallest scalar type capable of holding a PV).

$ perl -le'
   use Devel::Size qw( total_size );

   use Inline C => <<'\''__EOI__'\'';

      void upgrade_to_iv(SV* sv) {
         SvUPGRADE(sv, SVt_IV);
      }

      void upgrade_to_pv(SV* sv) {
         SvUPGRADE(sv, SVt_PV);
      }

__EOI__

   { my $x; upgrade_to_iv($x); print total_size($x); }
   { my $x; upgrade_to_pv($x); print total_size($x); }
'
24
40

Using an SvIV instead of an SvPV is a savings of 16 bytes per reference.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 1
    Trivia: The IV slot of an SvIV and the PV slot of an SvPV are located at the same offset. See [illguts](http://search.cpan.org/dist/illguts/) – ikegami Feb 10 '14 at 14:42
  • Thank you for your insightful answer! In my own experiments, I tried with and without blessing; in the former case, a PVMG structure is spawned, which does contain a PVX slot, adding to my confusion. I've just retried without blessing now, and indeed an SvIV structure is allocated as you write. I hadn't thought about about the memory savings, but that makes perfect sense now! – Edward Feb 12 '14 at 10:04
  • Re your comment: just tried it, and much to my surprise, SvPVX and SvIVX indeed return the same (stored) value! Seeing as the structure of SvIV and SvPV has been evolving through various versions of Perl, I guess I'm not supposed to rely on this, especially since SvPOK is not true. – Edward Feb 12 '14 at 10:28
  • SvPVMG is one of the larger types. It can hold an IV/UV/RV, an NV and a PV. It (or SvPVLV) is used for blessed and magical variables. (MG = magic) – ikegami Feb 12 '14 at 14:06
  • Yeah, don't use SvPVX that way! It'll fail for a SvPVIV, for example (whether SvPOK is true or not). – ikegami Feb 12 '14 at 14:07