diff options
author | David Mitchell <davem@iabyn.com> | 2017-07-07 14:13:32 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2017-07-27 11:30:21 +0100 |
commit | df6b4bd56551f2d39f7c0019c23f27181d8c39c4 (patch) | |
tree | 760cb0b40c0f202fe06ae67e0a239156b92597fe /sv.h | |
parent | e8f01ee5fa8087b34dfe31b2c53eef0ba8718922 (diff) | |
download | perl-df6b4bd56551f2d39f7c0019c23f27181d8c39c4.tar.gz |
give REGEXP SVs the POK flag again
Commit v5.17.5-99-g8d919b0 stopped SVt_REGEXP SVs (and PVLVs acting as
regexes) from having the POK and pPOK flags set. This made things like
SvOK() and SvTRUE() slower, because as well as the quick single test for
any I/N/P/R flags, SvOK() also has to test for
(SvTYPE(sv) == SVt_REGEXP
|| (SvFLAGS(sv) & (SVTYPEMASK|SVp_POK|SVpgv_GP|SVf_FAKE))
== (SVt_PVLV|SVf_FAKE))
This commit fixes the issue fixed by g8d919b0 in a slightly different way,
which is less invasive and allows the POK flag.
Background:
PVLV are basically PVMGs with a few extra fields. They are intended to
be a superset of all scalar types, so any scalar value can be assigned
to a PVLV SV.
However, once REGEXPs were made into first-class scalar SVs, this
assumption broke - there are a whole bunch of fields in a regex SV body
which can't be copied to to a PVLV. So this broke:
sub f {
my $r = qr/abc/; # $r is reference to an SVt_REGEXP
$_[0] = $$r;
}
f($h{foo}); # the hash access is deferred - a temporary PVLV is
# passed instead
The basic idea behind the g8d919b0 fix was, for an LV-acting-as-regex,
to attach both a PVLV body and a regex body to the SV head. This commit
keeps this basic concept; it just changes how the extra body is attached.
The original fix changed SVt_REGEXP SVs so that sv.sv_u.svu_pv no longer
pointed to the regexp's string representation; instead this pointer was
stored in a union made out of the xpv_len field. Doing this necessitated
not turning the POK flag on for any REGEXP SVs.
This freed up the sv_u to point to the regex body, while the sv_any field
could continue to point to the PVLV body. An ReANY() macro was introduced
that returned the sv_u field rather than the sv_any field.
This commit changes it so that instead, on regexp SVs (and LV-as-regexp
SVs), sv_u always points to the string buffer (so they can have POK set
again), but on specifically LV-as-regex SVs, the xpv_len_u union of the
PVLV body points to the regexp body.
This means that SVt_REGEXP SVs are now completely "normal" again,
and SVt_PVLV SVs are normal except in the one case where they hold a
regex, in which case rather than storing the string buffer's length, the
PVLV body stores a pointer to the regex body.
Diffstat (limited to 'sv.h')
-rw-r--r-- | sv.h | 20 |
1 files changed, 11 insertions, 9 deletions
@@ -208,7 +208,6 @@ typedef struct hek HEK; UV svu_uv; \ _NV_BODYLESS_UNION \ SV* svu_rv; /* pointer to another SV */ \ - struct regexp* svu_rx; \ SV** svu_array; \ HE** svu_hash; \ GP* svu_gp; \ @@ -402,7 +401,12 @@ perform the upgrade if necessary. See C<L</svtype>>. refers to an eval or once only [CvEVAL(cv), CvSPECIAL(cv)] 3: HV: informally reserved by DAPM - for vtables */ + for vtables + 4: Together with other flags (or + lack thereof) indicates a regex, + including PVLV-as-regex. See + isREGEXP(). + */ #define SVf_OOK 0x02000000 /* has valid offset value. For a PVHV this means that a hv_aux struct is present after the main array */ @@ -473,7 +477,7 @@ perform the upgrade if necessary. See C<L</svtype>>. STRLEN xpv_cur; /* length of svu_pv as a C string */ \ union { \ STRLEN xpvlenu_len; /* allocated size */ \ - char * xpvlenu_pv; /* regexp string */ \ + struct regexp* xpvlenu_rx; /* regex when SV body is XPVLV */ \ } xpv_len_u #define xpv_len xpv_len_u.xpvlenu_len @@ -847,7 +851,7 @@ Set the size of the string buffer for the SV. See C<L</SvLEN>>. #define assert_not_ROK(sv) assert_(!SvROK(sv) || !SvRV(sv)) #define assert_not_glob(sv) assert_(!isGV_with_GP(sv)) -#define SvOK(sv) (SvFLAGS(sv) & SVf_OK || isREGEXP(sv)) +#define SvOK(sv) (SvFLAGS(sv) & SVf_OK) #define SvOK_off(sv) (assert_not_ROK(sv) assert_not_glob(sv) \ SvFLAGS(sv) &= ~(SVf_OK| \ SVf_IVisUV|SVf_UTF8), \ @@ -1181,8 +1185,7 @@ object type. Exposed to perl code via Internals::SvREADONLY(). })) # define SvCUR(sv) \ (*({ const SV *const _svcur = (const SV *)(sv); \ - assert(PL_valid_types_PVX[SvTYPE(_svcur) & SVt_MASK] \ - || SvTYPE(_svcur) == SVt_REGEXP); \ + assert(PL_valid_types_PVX[SvTYPE(_svcur) & SVt_MASK]); \ assert(!isGV_with_GP(_svcur)); \ assert(!(SvTYPE(_svcur) == SVt_PVIO \ && !(IoFLAGS(_svcur) & IOf_FAKE_DIRP))); \ @@ -1312,8 +1315,7 @@ object type. Exposed to perl code via Internals::SvREADONLY(). (((XPVMG*) SvANY(sv))->xmg_stash = (val)); } STMT_END #define SvCUR_set(sv, val) \ STMT_START { \ - assert(PL_valid_types_PVX[SvTYPE(sv) & SVt_MASK] \ - || SvTYPE(sv) == SVt_REGEXP); \ + assert(PL_valid_types_PVX[SvTYPE(sv) & SVt_MASK]); \ assert(!isGV_with_GP(sv)); \ assert(!(SvTYPE(sv) == SVt_PVIO \ && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \ @@ -2128,7 +2130,7 @@ See also C<L</PL_sv_yes>> and C<L</PL_sv_no>>. } STMT_END #define isREGEXP(sv) \ (SvTYPE(sv) == SVt_REGEXP \ - || (SvFLAGS(sv) & (SVTYPEMASK|SVp_POK|SVpgv_GP|SVf_FAKE)) \ + || (SvFLAGS(sv) & (SVTYPEMASK|SVpgv_GP|SVf_FAKE)) \ == (SVt_PVLV|SVf_FAKE)) |