I'll be referring to this PDF, Reini Urban's PerlGuts Illustrated. It contains all the information needed to answer your question, but I'll arrange in the information in a more convenient format here.


There isn't just one type of scalar. See the graph at the bottom of the first page of the linked document. The ident that follows "SV =" indicates the type of the scalar. In this case, we have a SVt_IV.

The type of scalar controls what kind of values can be stored in that scalar. In a SVt_IV, one can store an IV (signed int) or a UV (unsigned int), but not a string or floating point number.

So what happens if you want to store a string inside the scalar? Well, Perl must first upgrade the scalar to a type that can handle the string. In this case, it will switch to a SVt_PVIV which can store a string in addition to a IV or UV.

$ perl -MDevel::Peek -e'my $x = 123; Dump($x); $x = "abc"; Dump($x);' SV = IV(0x2764760) at 0x2764770 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 123 SV = PVIV(0x2766c38) at 0x2764770 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) IV = 123 PV = 0x27c1258 "abc"\0 CUR = 3 LEN = 10 COW_REFCNT = 1

Tangent: Note that while the upgraded scalar can hold both a string and an IV/UV, it only contains a string because POK is set but not IOK. In other words, while the slot for an IV exists (and holds the old IV value), the slot isn't storing any part of the scalar's value at this time because of the flags.


The scalar is potentially referenced by multiple pointers, so how does Perl manage to upgrade the scalar to a larger one without invalidating those pointers? It does so by using two memory blocks to represent a scalar.

The second address in the dump is the address of the head. This is what the various pointers reference. As you can see, the address of the head didn't change when the scalar was upgraded.

Inside the head is a pointer to the second block, called the body. This is the first address in the dump. Upgrading a scalar upgrades a field in the head indicating the type of the scalar, and it replaces this block with a larger one.


Now, let's look at the 64-bit example.

Memory allocation is relatively expensive, so SVt_IV and SVt_RV utilize a hack to avoid memory allocation.

One would expects a SVt_IV scalar to look like this:

Head Body +---------------+ +---------------+ | Ptr to body -------> | IV/UV slot | +---------------+ +---------------+ | Ref count | +---------------+ | Flags & type | +---------------+ | Unused | +---------------+

Instead, it looks like this:

Head Body +---------------+ +---------------+ | Ptr to body -------> | Unused | +---------------+ +---------------+ | Ref count | | Unused | +---------------+ +---------------+ | Flags & type | | Unused | +---------------+ +---------------+ | Unused | | Unused | +---------------+ +---------------+ | IV/UV slot | +---------------+

Buy why? Perl gets (probably significant) performance gains by keeping the IV slot at the same offset into the body of a scalar regardless of the type of the scalar.

But I talked of a hack to avoid allocating a second memory block. We can avoid a memory allocation by overlapping both blocks!

+ - - - - - - - + Unallocated <--+ Head +---------------+ | | Ptr to body -------+ +---------------+ | Ref count | +---------------+ | Flags & type | +---------------+ | IV/UV slot | +---------------+

Now we have a single memory block that points to itself. This is found at the very top of page 12 of the linked document.


Finally, the answer to your question.

The size of some fields in the head and body are independent of architecture (especially since you set the integer size to 64-bits for both builds), and the size of other fields in the head and body are dependent of architecture (e.g. the size of a pointer).

The difference in the offset is based on differences in the total size of the head and body in the two builds.


In reply to Re: Understanding Devel::Peek output by ikegami
in thread Understanding Devel::Peek output by syphilis

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.