/* sv.h
*
* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- * 2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
+ * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
typedef enum {
SVt_NULL, /* 0 */
- SVt_IV, /* 1 */
- SVt_NV, /* 2 */
- SVt_RV, /* 3 */
- SVt_BIND, /* 4 */
- SVt_PV, /* 5 */
- SVt_PVIV, /* 6 */
- SVt_PVNV, /* 7 */
- SVt_PVMG, /* 8 */
+ SVt_BIND, /* 1 */
+ SVt_IV, /* 2 */
+ SVt_NV, /* 3 */
+ /* RV was here, before it was merged with IV. */
+ SVt_PV, /* 4 */
+ SVt_PVIV, /* 5 */
+ SVt_PVNV, /* 6 */
+ SVt_PVMG, /* 7 */
+ SVt_ORANGE, /* 8 */
/* PVBM was here, before BIND replaced it. */
SVt_PVGV, /* 9 */
SVt_PVLV, /* 10 */
purposes eternal code wanting to consider PVBM probably needs to think of
PVMG instead. */
# define SVt_PVBM SVt_PVMG
+/* Anything wanting to create a reference from clean should ensure that it has
+ a scalar of type SVt_IV now: */
+# define SVt_RV SVt_IV
#endif
/* There is collusion here with sv_clear - sv_clear exits early for SVt_NULL
and faster.
=for apidoc Am|SV*|SvREFCNT_inc_simple|SV* sv
-Same as SvREFCNT_inc, but can only be used with simple variables, not
-expressions or pointer dereferences. Since we don't have to store a
-temporary value, it's faster.
+Same as SvREFCNT_inc, but can only be used with expressions without side
+effects. Since we don't have to store a temporary value, it's faster.
=for apidoc Am|SV*|SvREFCNT_inc_simple_NN|SV* sv
Same as SvREFCNT_inc_simple, but can only be used if you know I<sv>
#endif
#define SVTYPEMASK 0xff
-#define SvTYPE(sv) (svtype)((sv)->sv_flags & SVTYPEMASK)
+#define SvTYPE(sv) ((svtype)((sv)->sv_flags & SVTYPEMASK))
/* Sadly there are some parts of the core that have pointers to already-freed
SV heads, and rely on being able to tell that they are now free. So mark
means that a hv_aux struct is present
after the main array */
#define SVf_BREAK 0x04000000 /* refcnt is artificially low - used by
- SV's in final arena cleanup */
+ SV's in final arena cleanup */
#define SVf_READONLY 0x08000000 /* may not be modified */
#define PRIVSHIFT 4 /* (SVp_?OK >> PRIVSHIFT) == SVf_?OK */
#define SVf_AMAGIC 0x10000000 /* has magical overloaded methods */
+
+/* Ensure this value does not clash with the GV_ADD* flags in gv.h: */
#define SVf_UTF8 0x20000000 /* SvPV is UTF-8 encoded
This is also set on RVs whose overloaded
stringification is UTF-8. This might
only happen as a side effect of SvPV() */
-/* Ensure this value does not clash with the GV_ADD* flags in gv.h */
/* Some private flags. */
+/* PVAV could probably use 0x2000000 without conflict. I assume that PVFM can
+ be UTF-8 encoded, and PVCVs could well have UTF-8 prototypes. PVIOs haven't
+ been restructured, so sometimes get used as string buffers. */
+
/* PVHV */
#define SVphv_SHAREKEYS 0x20000000 /* PVHV keys live on shared string table */
/* PVNV, PVMG, presumably only inside pads */
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
};
-#if 0
-typedef struct xpv xpv_allocated;
-#else
typedef struct {
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
} xpv_allocated;
-#endif
struct xpviv {
union {
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
} xiv_u;
};
-#if 0
-typedef struct xpviv xpviv_allocated;
-#else
typedef struct {
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
HEK * xivu_namehek;
} xiv_u;
} xpviv_allocated;
-#endif
#define xiv_iv xiv_u.xivu_iv
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* xgv_flags */
STRLEN xpv_len; /* 0 */
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
U32 xlow;
U32 xhigh;
} xpad_cop_seq; /* used by pad.c for cop_sequence */
+ struct {
+ U32 xbm_previous; /* how many characters in string before rare? */
+ U8 xbm_flags;
+ U8 xbm_rare; /* rarest character in string */
+ } xbm_s; /* fields from PVBM */
} xnv_u;
STRLEN xpv_cur; /* length of svu_pv as a C string */
STRLEN xpv_len; /* allocated size */
GV * xio_fmt_gv; /* $~ */
char * xio_bottom_name;/* $^B */
GV * xio_bottom_gv; /* $^B */
- short xio_subprocess; /* -| or |- */
char xio_type;
- char xio_flags;
+ U8 xio_flags;
};
#define xio_dirp xio_dirpu.xiou_dirp
#define xio_any xio_dirpu.xiou_any
/* The following macros define implementation-independent predicates on SVs. */
/*
-=for apidoc Am|bool|SvNIOK|SV* sv
-Returns a boolean indicating whether the SV contains a number, integer or
+=for apidoc Am|U32|SvNIOK|SV* sv
+Returns a U32 value indicating whether the SV contains a number, integer or
double.
-=for apidoc Am|bool|SvNIOKp|SV* sv
-Returns a boolean indicating whether the SV contains a number, integer or
+=for apidoc Am|U32|SvNIOKp|SV* sv
+Returns a U32 value indicating whether the SV contains a number, integer or
double. Checks the B<private> setting. Use C<SvNIOK>.
=for apidoc Am|void|SvNIOK_off|SV* sv
Unsets the NV/IV status of an SV.
-=for apidoc Am|bool|SvOK|SV* sv
-Returns a boolean indicating whether the value is an SV. It also tells
+=for apidoc Am|U32|SvOK|SV* sv
+Returns a U32 value indicating whether the value is an SV. It also tells
whether the value is defined or not.
-=for apidoc Am|bool|SvIOKp|SV* sv
-Returns a boolean indicating whether the SV contains an integer. Checks
+=for apidoc Am|U32|SvIOKp|SV* sv
+Returns a U32 value indicating whether the SV contains an integer. Checks
the B<private> setting. Use C<SvIOK>.
-=for apidoc Am|bool|SvNOKp|SV* sv
-Returns a boolean indicating whether the SV contains a double. Checks the
+=for apidoc Am|U32|SvNOKp|SV* sv
+Returns a U32 value indicating whether the SV contains a double. Checks the
B<private> setting. Use C<SvNOK>.
-=for apidoc Am|bool|SvPOKp|SV* sv
-Returns a boolean indicating whether the SV contains a character string.
+=for apidoc Am|U32|SvPOKp|SV* sv
+Returns a U32 value indicating whether the SV contains a character string.
Checks the B<private> setting. Use C<SvPOK>.
-=for apidoc Am|bool|SvIOK|SV* sv
-Returns a boolean indicating whether the SV contains an integer.
+=for apidoc Am|U32|SvIOK|SV* sv
+Returns a U32 value indicating whether the SV contains an integer.
=for apidoc Am|void|SvIOK_on|SV* sv
Tells an SV that it is an integer.
=for apidoc Am|bool|SvIOK_UV|SV* sv
Returns a boolean indicating whether the SV contains an unsigned integer.
-=for apidoc Am|void|SvUOK|SV* sv
+=for apidoc Am|bool|SvUOK|SV* sv
Returns a boolean indicating whether the SV contains an unsigned integer.
=for apidoc Am|bool|SvIOK_notUV|SV* sv
Returns a boolean indicating whether the SV contains a signed integer.
-=for apidoc Am|bool|SvNOK|SV* sv
-Returns a boolean indicating whether the SV contains a double.
+=for apidoc Am|U32|SvNOK|SV* sv
+Returns a U32 value indicating whether the SV contains a double.
=for apidoc Am|void|SvNOK_on|SV* sv
Tells an SV that it is a double.
=for apidoc Am|void|SvNOK_only|SV* sv
Tells an SV that it is a double and disables all other OK bits.
-=for apidoc Am|bool|SvPOK|SV* sv
-Returns a boolean indicating whether the SV contains a character
+=for apidoc Am|U32|SvPOK|SV* sv
+Returns a U32 value indicating whether the SV contains a character
string.
=for apidoc Am|void|SvPOK_on|SV* sv
=for apidoc Am|bool|SvVOK|SV* sv
Returns a boolean indicating whether the SV contains a v-string.
-=for apidoc Am|bool|SvOOK|SV* sv
-Returns a boolean indicating whether the SvIVX is a valid offset value for
+=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).
-=for apidoc Am|bool|SvROK|SV* sv
+=for apidoc Am|U32|SvROK|SV* sv
Tests if the SV is an RV.
=for apidoc Am|void|SvROK_on|SV* sv
#define assert_not_glob(sv)
#endif
-#define SvOK(sv) (SvFLAGS(sv) & SVf_OK)
+#define SvOK(sv) ((SvTYPE(sv) == SVt_BIND) \
+ ? (SvFLAGS(SvRV(sv)) & SVf_OK) \
+ : (SvFLAGS(sv) & SVf_OK))
#define SvOK_off(sv) (assert_not_ROK(sv) assert_not_glob(sv) \
SvFLAGS(sv) &= ~(SVf_OK| \
SVf_IVisUV|SVf_UTF8), \
SvFLAGS(sv) |= (SVf_NOK|SVp_NOK))
/*
-=for apidoc Am|bool|SvUTF8|SV* sv
-Returns a boolean indicating whether the SV contains UTF-8 encoded data.
+=for apidoc Am|U32|SvUTF8|SV* sv
+Returns a U32 value indicating whether the SV contains UTF-8 encoded data.
Call this after SvPV() in case any call to string overloading updates the
internal flag.
# define SvPAD_STATE_on(sv) (SvFLAGS(sv) |= SVpad_NAME|SVpad_STATE)
#endif
-#define OURSTASH(sv) \
+#define SvOURSTASH(sv) \
(SvPAD_OUR(sv) ? ((XPVMG*) SvANY(sv))->xmg_u.xmg_ourstash : NULL)
-#define OURSTASH_set(sv, st) \
+#define SvOURSTASH_set(sv, st) \
STMT_START { \
assert(SvTYPE(sv) == SVt_PVMG); \
((XPVMG*) SvANY(sv))->xmg_u.xmg_ourstash = st; \
} STMT_END
#ifdef PERL_DEBUG_COW
-#define SvRV(sv) (0 + (sv)->sv_u.svu_rv)
#else
-#define SvRV(sv) ((sv)->sv_u.svu_rv)
#endif
#define SvRVx(sv) SvRV(sv)
# define SvIVX(sv) (0 + ((XPVIV*) SvANY(sv))->xiv_iv)
# define SvUVX(sv) (0 + ((XPVUV*) SvANY(sv))->xuv_uv)
# define SvNVX(sv) (-0.0 + ((XPVNV*) SvANY(sv))->xnv_u.xnv_nv)
+# define SvRV(sv) (0 + (sv)->sv_u.svu_rv)
/* Don't test the core XS code yet. */
# if defined (PERL_CORE) && PERL_DEBUG_COW > 1
# define SvPVX(sv) (0 + (assert(!SvREADONLY(sv)), (sv)->sv_u.svu_pv))
assert(!isGV_with_GP(_svi)); \
&(((XPVNV*) SvANY(_svi))->xnv_u.xnv_nv); \
}))
+# define SvRV(sv) \
+ (*({ SV *const _svi = (SV *) (sv); \
+ assert(SvTYPE(_svi) >= SVt_PV || SvTYPE(_svi) == SVt_IV); \
+ assert(SvTYPE(_svi) != SVt_PVAV); \
+ assert(SvTYPE(_svi) != SVt_PVHV); \
+ assert(SvTYPE(_svi) != SVt_PVCV); \
+ assert(SvTYPE(_svi) != SVt_PVFM); \
+ assert(!isGV_with_GP(_svi)); \
+ &((_svi)->sv_u.svu_rv); \
+ }))
# define SvMAGIC(sv) \
(*({ SV *const _svi = (SV *) (sv); \
assert(SvTYPE(_svi) >= SVt_PVMG); \
# define SvIVX(sv) ((XPVIV*) SvANY(sv))->xiv_iv
# define SvUVX(sv) ((XPVUV*) SvANY(sv))->xuv_uv
# define SvNVX(sv) ((XPVNV*) SvANY(sv))->xnv_u.xnv_nv
+# define SvRV(sv) ((sv)->sv_u.svu_rv)
# define SvMAGIC(sv) ((XPVMG*) SvANY(sv))->xmg_u.xmg_magic
# define SvSTASH(sv) ((XPVMG*) SvANY(sv))->xmg_stash
# endif
assert(!isGV_with_GP(sv)); \
(((XPVUV*)SvANY(sv))->xuv_uv = (val)); } STMT_END
#define SvRV_set(sv, val) \
- STMT_START { assert(SvTYPE(sv) >= SVt_RV); \
+ STMT_START { assert(SvTYPE(sv) >= SVt_PV || SvTYPE(sv) == SVt_IV); \
+ assert(SvTYPE(sv) != SVt_PVAV); \
+ assert(SvTYPE(sv) != SVt_PVHV); \
+ assert(SvTYPE(sv) != SVt_PVCV); \
+ assert(SvTYPE(sv) != SVt_PVFM); \
assert(!isGV_with_GP(sv)); \
((sv)->sv_u.svu_rv = (val)); } STMT_END
#define SvMAGIC_set(sv, val) \
STMT_START { \
assert(SvTYPE(sv) >= SVt_PV); \
if (SvLEN(sv)) { \
+ assert(!SvROK(sv)); \
if(SvOOK(sv)) { \
SvPV_set(sv, SvPVX_mutable(sv) - SvIVX(sv)); \
SvFLAGS(sv) &= ~SVf_OOK; \
} STMT_END
-#define PERL_FBM_TABLE_OFFSET 5 /* Number of bytes between EOS and table */
-#define PERL_FBM_FLAGS_OFFSET_FROM_TABLE -1
-/* how many characters in string before rare? */
-#if (BYTEORDER == 0x4321) || (BYTEORDER == 0x87654321)
-# define PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE -2
-# define PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE -3
-#else
-# define PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE -2
-# define PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE -3
-#endif
-/* rarest character in string */
-#define PERL_FBM_RARE_OFFSET_FROM_TABLE -4
+#define PERL_FBM_TABLE_OFFSET 1 /* Number of bytes between EOS and table */
/* SvPOKp not SvPOK in the assertion because the string can be tainted! eg
perl -T -e '/$^X/'
*/
#if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
+# define BmFLAGS(sv) \
+ (*({ SV *const uggh = (SV *) (sv); \
+ assert(SvTYPE(uggh) == SVt_PVGV); \
+ assert(SvVALID(uggh)); \
+ &(((XPVGV*) SvANY(uggh))->xnv_u.xbm_s.xbm_flags); \
+ }))
# define BmRARE(sv) \
(*({ SV *const uggh = (SV *) (sv); \
assert(SvTYPE(uggh) == SVt_PVGV); \
assert(SvVALID(uggh)); \
- assert(SvCUR(uggh) + PERL_FBM_TABLE_OFFSET \
- + PERL_FBM_RARE_OFFSET_FROM_TABLE <= SvLEN(uggh)); \
- assert(SvPOKp(uggh)); \
- (U8*)(SvEND(uggh) \
- + PERL_FBM_TABLE_OFFSET + PERL_FBM_RARE_OFFSET_FROM_TABLE); \
+ &(((XPVGV*) SvANY(uggh))->xnv_u.xbm_s.xbm_rare); \
}))
# define BmUSEFUL(sv) \
(*({ SV *const uggh = (SV *) (sv); \
&(((XPVGV*) SvANY(uggh))->xiv_u.xivu_i32); \
}))
# define BmPREVIOUS(sv) \
- ({ SV *const uggh = (SV *) (sv); \
- assert(SvTYPE(uggh) == SVt_PVGV); \
- assert(SvVALID(uggh)); \
- assert(SvPOKp(uggh)); \
- assert(SvCUR(uggh) + PERL_FBM_TABLE_OFFSET <= SvLEN(uggh)); \
- (*(U8*)(SvEND(uggh) + PERL_FBM_TABLE_OFFSET \
- + PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE) << 8) \
- | (*(U8*)(SvEND(uggh) + PERL_FBM_TABLE_OFFSET \
- + PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE)); \
- })
+ (*({ SV *const uggh = (SV *) (sv); \
+ assert(SvTYPE(uggh) == SVt_PVGV); \
+ assert(SvVALID(uggh)); \
+ &(((XPVGV*) SvANY(uggh))->xnv_u.xbm_s.xbm_previous); \
+ }))
#else
-# define BmRARE(sv) \
- (*(U8*)(SvEND(sv) \
- + PERL_FBM_TABLE_OFFSET + PERL_FBM_RARE_OFFSET_FROM_TABLE))
-
-# define BmUSEFUL(sv) ((XPVGV*) SvANY(sv))->xiv_u.xivu_i32
-# define BmPREVIOUS(sv) \
- ((*(U8*)(SvEND(sv) + PERL_FBM_TABLE_OFFSET \
- + PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE) << 8) \
- | (*(U8*)(SvEND(sv) + PERL_FBM_TABLE_OFFSET \
- + PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE))) \
+# define BmFLAGS(sv) ((XPVGV*) SvANY(sv))->xnv_u.xbm_s.xbm_flags
+# define BmRARE(sv) ((XPVGV*) SvANY(sv))->xnv_u.xbm_s.xbm_rare
+# define BmUSEFUL(sv) ((XPVGV*) SvANY(sv))->xiv_u.xivu_i32
+# define BmPREVIOUS(sv) ((XPVGV*) SvANY(sv))->xnv_u.xbm_s.xbm_previous
#endif
-#define BmPREVIOUS_set(sv, val) \
- STMT_START { assert(SvTYPE(sv) == SVt_PVGV); \
- assert(SvVALID(sv)); \
- assert(SvPOKp(sv)); \
- assert(SvCUR(sv) + PERL_FBM_TABLE_OFFSET <= SvLEN(sv)); \
- *(U8*)(SvEND(sv) + PERL_FBM_TABLE_OFFSET \
- + PERL_FBM_PREVIOUS_H_OFFSET_FROM_TABLE) = (U8)((U32)(val)>>8); \
- *(U8*)(SvEND(sv) + PERL_FBM_TABLE_OFFSET \
- + PERL_FBM_PREVIOUS_L_OFFSET_FROM_TABLE) = (U8)(val); \
- } STMT_END
#define FmLINES(sv) ((XPVFM*) SvANY(sv))->xfm_lines
#define IoFMT_GV(sv) ((XPVIO*) SvANY(sv))->xio_fmt_gv
#define IoBOTTOM_NAME(sv)((XPVIO*) SvANY(sv))->xio_bottom_name
#define IoBOTTOM_GV(sv) ((XPVIO*) SvANY(sv))->xio_bottom_gv
-#define IoSUBPROCESS(sv)((XPVIO*) SvANY(sv))->xio_subprocess
#define IoTYPE(sv) ((XPVIO*) SvANY(sv))->xio_type
#define IoFLAGS(sv) ((XPVIO*) SvANY(sv))->xio_flags
C<SvPVx> for a version which guarantees to evaluate sv only once.
=for apidoc Am|char*|SvPVx|SV* sv|STRLEN len
-A version of C<SvPV> which guarantees to evaluate sv only once.
+A version of C<SvPV> which guarantees to evaluate C<sv> only once.
+Only use this if C<sv> is an expression with side effects, otherwise use the
+more efficient C<SvPVX>.
=for apidoc Am|char*|SvPV_nomg|SV* sv|STRLEN len
Like C<SvPV> but doesn't process magic.
stringified form becoming C<SvPOK>. Handles 'get' magic.
=for apidoc Am|IV|SvIV|SV* sv
-Coerces the given SV to an integer and returns it. See C<SvIVx> for a
+Coerces the given SV to an integer and returns it. See C<SvIVx> for a
version which guarantees to evaluate sv only once.
=for apidoc Am|IV|SvIV_nomg|SV* sv
=for apidoc Am|IV|SvIVx|SV* sv
Coerces the given SV to an integer and returns it. Guarantees to evaluate
-sv only once. Use the more efficient C<SvIV> otherwise.
+C<sv> only once. Only use this if C<sv> is an expression with side effects,
+otherwise use the more efficient C<SvIV>.
=for apidoc Am|NV|SvNV|SV* sv
-Coerce the given SV to a double and return it. See C<SvNVx> for a version
+Coerce the given SV to a double and return it. See C<SvNVx> for a version
which guarantees to evaluate sv only once.
=for apidoc Am|NV|SvNVx|SV* sv
Coerces the given SV to a double and returns it. Guarantees to evaluate
-sv only once. Use the more efficient C<SvNV> otherwise.
+C<sv> only once. Only use this if C<sv> is an expression with side effects,
+otherwise use the more efficient C<SvNV>.
=for apidoc Am|UV|SvUV|SV* sv
Coerces the given SV to an unsigned integer and returns it. See C<SvUVx>
=for apidoc Am|UV|SvUVx|SV* sv
Coerces the given SV to an unsigned integer and returns it. Guarantees to
-evaluate sv only once. Use the more efficient C<SvUV> otherwise.
+C<sv> only once. Only use this if C<sv> is an expression with side effects,
+otherwise use the more efficient C<SvUV>.
=for apidoc Am|bool|SvTRUE|SV* sv
Returns a boolean indicating whether Perl would evaluate the SV as true or
#define SV_SMAGIC 128
#define SV_HAS_TRAILING_NUL 256
#define SV_COW_SHARED_HASH_KEYS 512
+/* This one is only enabled for PERL_OLD_COPY_ON_WRITE */
+#define SV_COW_OTHER_PVS 1024
/* The core is safe for this COW optimisation. XS code on CPAN may not be.
So only default to doing the COW setup if we're in the core.
*/
#ifdef PERL_CORE
# ifndef SV_DO_COW_SVSETSV
-# define SV_DO_COW_SVSETSV SV_COW_SHARED_HASH_KEYS
+# define SV_DO_COW_SVSETSV SV_COW_SHARED_HASH_KEYS|SV_COW_OTHER_PVS
# endif
#endif
sv_force_normal_flags(sv, SV_COW_DROP_PV)
#ifdef PERL_OLD_COPY_ON_WRITE
-# define SvRELEASE_IVX(sv) ((void)((SvFLAGS(sv) & (SVf_OOK|SVf_READONLY|SVf_FAKE)) \
- && Perl_sv_release_IVX(aTHX_ sv)))
+#define SvRELEASE_IVX(sv) \
+ ((SvIsCOW(sv) ? sv_force_normal_flags(sv, 0) : (void) 0), SvOOK_off(sv))
# define SvIsCOW_normal(sv) (SvIsCOW(sv) && SvLEN(sv))
#else
# define SvRELEASE_IVX(sv) SvOOK_off(sv)
#define SvSHARE(sv) CALL_FPTR(PL_sharehook)(aTHX_ sv)
#define SvLOCK(sv) CALL_FPTR(PL_lockhook)(aTHX_ sv)
#define SvUNLOCK(sv) CALL_FPTR(PL_unlockhook)(aTHX_ sv)
+#define SvDESTROYABLE(sv) CALL_FPTR(PL_destroyhook)(aTHX_ sv)
#define SvGETMAGIC(x) STMT_START { if (SvGMAGICAL(x)) mg_get(x); } STMT_END
#define SvSETMAGIC(x) STMT_START { if (SvSMAGICAL(x)) mg_set(x); } STMT_END