diff options
author | Nicholas Clark <nick@ccl4.org> | 2008-01-05 11:30:31 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2008-01-05 11:30:31 +0000 |
commit | 69240efd70fee399a5232ed995c383b154000a08 (patch) | |
tree | 79c33453a3adc1fdccc1d469a75b1aeb49898614 /sv.h | |
parent | bdd9a1b1ec56a0b6b7d8b1b363138a8fbd3040e3 (diff) | |
download | perl-69240efd70fee399a5232ed995c383b154000a08.tar.gz |
BER is all very well, but it turns out that it's better to store the
offset as either a byte (if <256), or a 0 byte with a STRLEN before.
"better" in that the reading can be inlined, and even then the object
code is smaller (function calls have space overhead). So goodbye
Perl_sv_read_offset() and hello SvOOK_offset().
p4raw-id: //depot/perl@32838
Diffstat (limited to 'sv.h')
-rw-r--r-- | sv.h | 69 |
1 files changed, 63 insertions, 6 deletions
@@ -653,10 +653,12 @@ Will also turn off the UTF-8 status. Returns a boolean indicating whether the SV contains a v-string. =for apidoc Am|U32|SvOOK|SV* sv -Returns a U32 indicating whether the SvIVX is a valid offset value for -the SvPVX. This hack is used internally to speed up removal of characters -from the beginning of a SvPV. When SvOOK is true, then the start of the -allocated string buffer is really (SvPVX - SvIVX). +Returns a U32 indicating whether the pointer to the string buffer is offset. +This hack is used internally to speed up removal of characters from the +beginning of a SvPV. When SvOOK is true, then the start of the +allocated string buffer is actually C<SvOOK_offset()> bytes before SvPVX. +This offset used to be stored in SvIVX, but is now stored within the spare +part of the buffer. =for apidoc Am|U32|SvROK|SV* sv Tests if the SV is an RV. @@ -1240,8 +1242,9 @@ the scalar's value cannot change unless written to. if (SvLEN(sv)) { \ assert(!SvROK(sv)); \ if(SvOOK(sv)) { \ - SvPV_set(sv, SvPVX_mutable(sv) \ - - sv_read_offset(sv)); \ + STRLEN zok; \ + SvOOK_offset(sv, zok); \ + SvPV_set(sv, SvPVX_mutable(sv) - zok); \ SvFLAGS(sv) &= ~SVf_OOK; \ } \ Safefree(SvPVX(sv)); \ @@ -1929,6 +1932,60 @@ C<SvUTF8_on> on the new SV. Implemented as a wrapper around C<newSVpvn_flags>. #define newSVpvn_utf8(s, len, u) newSVpvn_flags((s), (len), (u) ? SVf_UTF8 : 0) /* +=for apidoc Am|void|SvOOK_offset|NN SV*sv|STRLEN len + +Reads into I<len> the offset from SvPVX back to the true start of the +allocated buffer, which will be non-zero if C<sv_chop> has been used to +efficiently remove characters from start of the buffer. Implemented as a +macro, which takes the address of I<len>, which must be of type C<STRLEN>. +Evaluates I<sv> more than once. Sets I<len> to 0 if C<SvOOK(sv)> is false. + +=cut +*/ + +#ifdef DEBUGGING +/* Does the bot know something I don't? +10:28 <@Nicholas> metabatman +10:28 <+meta> Nicholas: crash +*/ +# define SvOOK_offset(sv, offset) STMT_START { \ + assert(sizeof(offset) == sizeof(STRLEN)); \ + if (SvOOK(sv)) { \ + const U8 *crash = (U8*)SvPVX_const(sv); \ + offset = *--crash; \ + if (!offset) { \ + crash -= sizeof(STRLEN); \ + Copy(crash, (U8 *)&offset, sizeof(STRLEN), U8); \ + } \ + { \ + /* Validate the preceding buffer's sentinels to \ + verify that no-one is using it. */ \ + const U8 *const bonk = (U8 *) SvPVX_const(sv) - offset; \ + while (crash > bonk) { \ + --crash; \ + assert (*crash == (U8)PTR2UV(crash)); \ + } \ + } \ + } else { \ + offset = 0; \ + } \ + } STMT_END +#else + /* This is the same code, but avoids using any temporary variables: */ +# define SvOOK_offset(sv, offset) STMT_START { \ + assert(sizeof(offset) == sizeof(STRLEN)); \ + if (SvOOK(sv)) { \ + offset = ((U8*)SvPVX_const(sv))[-1]; \ + if (!offset) { \ + Copy(SvPVX_const(sv) - 1 - sizeof(STRLEN), \ + (U8 *)&offset, sizeof(STRLEN), U8); \ + } \ + } else { \ + offset = 0; \ + } \ + } STMT_END +#endif +/* * Local variables: * c-indentation-style: bsd * c-basic-offset: 4 |