The "SvPVX_readonly" task
[email protected] (Nicholas Clark) Wed, 4 May 2005 22:50:36 +0100
| Newsgroups | perl.perl5.porters,perl.ponie.dev |
|---|---|
| Message-ID | <[email protected]> |
Clarification about what I was thinking in the "SvPVX_readonly" task in the
Ponie roadmap:
At the moment in the perl core, there is a lot of code like this:
char *s = SvPVX(sv);
Several different things can happen next to s, or more importantly the memory
pointed to by s
1: It can be written to
*s = '\0';
(etc)
Clearly s here is correctly a non-const char *.
Also in this category would be passing s to a function that writes to the
memory.
2: s can be accessed to read the memory, but not write to it. So the code can
be re-written as
const char *s = SvPVX(sv);
without the compiler pitching a fit.
Likewise s could be passed to a function accepting a const char * pointer,
or anything else that won't write to the memory.
So it would be useful to distinguish the 2 cases, and replace all of the
latter class with a new macro that (in effect) returns a (const char *)
This actually benefits core Perl 5, as any COW (Copy On Write) scheme would
know that for this case, there isn't about to be a write, so it doesn't need to
do a copy. If this isn't done, then the core needs to be pessimistic, and every
SvPVX becomes a "do the copy" point.
Anyway, as to Ponie - currently the plan is for Ponie to store string data in
Parrot's STRING type, which is COW, and more appropriate for interacting with
other Parrot based languages such as Perl 6. To provide source level
compatibility with Perl 5 XS code, the plan is that a call to SvPVX will cause
the PMC to copy out the STRING to a scratch buffer, read-write, which the PMC
will reel back in at end of scope and update the STRING with. (plus at any
time when the vtable get_string() is called). This means that a plain SvPVX
has to be treated as a read-write operation, and incur both the Copy cost in
COW and the end of scope fixup. Hence knowing that a request for a Perl 5
style buffer is going to be read only will be cheaper to fulfil. Hence go-
faster Ponie.
Actually, case 2 can be divided further:
2a: Pointer to a read only buffer that is '\0' terminated, because it's about
to be passed to a function that expects a C '\0' terminated string. eg:
!PerlLIO_stat(SvPVX(tmpglob),&st)
2b: Pointer to a read only buffer that doesn't have to be '\0' terminated
because it's being accessed by or passed to functions that use a length
parameter
The reason this division is potentially useful is because Parrot's STRINGs
aren't automatically '\0' terminated, and can even do COW for substrings, so
a 2a request might mean copying to a temporary buffer just to add a '\0', to
meet the Perl 5 requirement that SvPVX[SvCUR] == '\0'. Whereas if the caller
indicates that it doesn't require the strict Perl 5 interpretation, it may
well be possible to return a (most definitely read only) pointer into the
STRING's internal storage.
I wonder if case 1 can also be divided into "I'm going to modify what's
there" and "Whatever was there is toast. I'm writing all over it"
Nicholas Clark
PS "code can be re-written as" should probably be rephrased as
"Andy has already sent a patch to do this", given how productive he's been.