summaryrefslogtreecommitdiff
path: root/sv.h
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2008-01-05 11:30:31 +0000
committerNicholas Clark <nick@ccl4.org>2008-01-05 11:30:31 +0000
commit69240efd70fee399a5232ed995c383b154000a08 (patch)
tree79c33453a3adc1fdccc1d469a75b1aeb49898614 /sv.h
parentbdd9a1b1ec56a0b6b7d8b1b363138a8fbd3040e3 (diff)
downloadperl-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.h69
1 files changed, 63 insertions, 6 deletions
diff --git a/sv.h b/sv.h
index afa18dc527..e13b5ba3f4 100644
--- a/sv.h
+++ b/sv.h
@@ -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