summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2017-07-03 17:07:28 +0100
committerDavid Mitchell <davem@iabyn.com>2017-07-27 11:30:21 +0100
commit5a6c28370397ad3d5c138df5778833dc4b11c3be (patch)
tree220b9b186bb82e9ed21290c3f93130b906e3ba27
parent0283ad960acb937e9387b3323f1f7852c2adb0fa (diff)
downloadperl-5a6c28370397ad3d5c138df5778833dc4b11c3be.tar.gz
add PL_sv_zero
it's like PL_sv_no, except that its string value is "0" rather than "". It can be used for example where pp function wants to push a zero return value on the stack. The next commit will start to use it. Also update the SvIMMORTAL() to be more efficient: it now checks whether the SV's address is in a range rather than individually checking against &PL_sv_undef, &PL_sv_no etc.
-rw-r--r--dump.c15
-rw-r--r--embedvar.h1
-rw-r--r--globvar.sym1
-rw-r--r--intrpvar.h8
-rw-r--r--perl.c5
-rw-r--r--perl.h2
-rw-r--r--sv.c13
-rw-r--r--sv.h2
8 files changed, 45 insertions, 2 deletions
diff --git a/dump.c b/dump.c
index c4bb3ce09c..fa5f0baf91 100644
--- a/dump.c
+++ b/dump.c
@@ -369,7 +369,9 @@ Perl_sv_peek(pTHX_ SV *sv)
sv_catpv(t, "WILD");
goto finish;
}
- else if (sv == &PL_sv_undef || sv == &PL_sv_no || sv == &PL_sv_yes || sv == &PL_sv_placeholder) {
+ else if ( sv == &PL_sv_undef || sv == &PL_sv_no || sv == &PL_sv_yes
+ || sv == &PL_sv_zero || sv == &PL_sv_placeholder)
+ {
if (sv == &PL_sv_undef) {
sv_catpv(t, "SV_UNDEF");
if (!(SvFLAGS(sv) & (SVf_OK|SVf_OOK|SVs_OBJECT|
@@ -398,6 +400,17 @@ Perl_sv_peek(pTHX_ SV *sv)
SvNVX(sv) == 1.0)
goto finish;
}
+ else if (sv == &PL_sv_zero) {
+ sv_catpv(t, "SV_ZERO");
+ if (!(SvFLAGS(sv) & (SVf_ROK|SVf_OOK|SVs_OBJECT|
+ SVs_GMG|SVs_SMG|SVs_RMG)) &&
+ !(~SvFLAGS(sv) & (SVf_POK|SVf_NOK|SVf_READONLY|
+ SVp_POK|SVp_NOK)) &&
+ SvCUR(sv) == 1 &&
+ SvPVX_const(sv) && *SvPVX_const(sv) == '0' &&
+ SvNVX(sv) == 0.0)
+ goto finish;
+ }
else {
sv_catpv(t, "SV_PLACEHOLDER");
if (!(SvFLAGS(sv) & (SVf_OK|SVf_OOK|SVs_OBJECT|
diff --git a/embedvar.h b/embedvar.h
index 1e3f9a2ed9..4b945f26ab 100644
--- a/embedvar.h
+++ b/embedvar.h
@@ -322,6 +322,7 @@
#define PL_sv_serial (vTHX->Isv_serial)
#define PL_sv_undef (vTHX->Isv_undef)
#define PL_sv_yes (vTHX->Isv_yes)
+#define PL_sv_zero (vTHX->Isv_zero)
#define PL_sys_intern (vTHX->Isys_intern)
#define PL_taint_warn (vTHX->Itaint_warn)
#define PL_tainted (vTHX->Itainted)
diff --git a/globvar.sym b/globvar.sym
index c82dc8f1c8..a91d520306 100644
--- a/globvar.sym
+++ b/globvar.sym
@@ -3,6 +3,7 @@
# *** Usual globals initialized at runtime should be added in *var*.h.
PL_No
+PL_Zero
PL_Yes
PL_bincompat_options
PL_bitcount
diff --git a/intrpvar.h b/intrpvar.h
index c6070eab43..e1c96f71e5 100644
--- a/intrpvar.h
+++ b/intrpvar.h
@@ -158,12 +158,20 @@ C<&PL_sv_no>.
This is the C<true> SV. See C<L</PL_sv_no>>. Always refer to this as
C<&PL_sv_yes>.
+=for apidoc Amn|SV|PL_sv_zero
+This readonly SV has a zero numeric value and a C<"0"> string value. It's
+similar to C<L</PL_sv_no>> except for its string value. Can be used as a
+cheap alternative to C<mXPUSHi(0)> for example. Always refer to this as
+C<&PL_sv_zero>. Introduced in 5.28.
+
=cut
*/
PERLVAR(I, sv_undef, SV)
PERLVAR(I, sv_no, SV)
PERLVAR(I, sv_yes, SV)
+PERLVAR(I, sv_zero, SV)
+
PERLVAR(I, padname_undef, PADNAME)
PERLVAR(I, padname_const, PADNAME)
PERLVAR(I, Sv, SV *) /* used to hold temporary values */
diff --git a/perl.c b/perl.c
index 3497043d79..4370f48d48 100644
--- a/perl.c
+++ b/perl.c
@@ -1287,6 +1287,11 @@ perl_destruct(pTHXx)
SvANY(&PL_sv_no) = NULL;
SvFLAGS(&PL_sv_no) = 0;
+ SvREFCNT(&PL_sv_zero) = 0;
+ sv_clear(&PL_sv_zero);
+ SvANY(&PL_sv_zero) = NULL;
+ SvFLAGS(&PL_sv_zero) = 0;
+
{
int i;
for (i=0; i<=2; i++) {
diff --git a/perl.h b/perl.h
index 01f8960b63..db1b5b318e 100644
--- a/perl.h
+++ b/perl.h
@@ -4766,6 +4766,8 @@ EXTCONST char PL_Yes[]
INIT("1");
EXTCONST char PL_No[]
INIT("");
+EXTCONST char PL_Zero[]
+ INIT("0");
EXTCONST char PL_hexdigit[]
INIT("0123456789abcdef0123456789ABCDEF");
diff --git a/sv.c b/sv.c
index cb3c1d128c..5a554fe17c 100644
--- a/sv.c
+++ b/sv.c
@@ -15407,6 +15407,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
init_constants();
ptr_table_store(PL_ptr_table, &proto_perl->Isv_undef, &PL_sv_undef);
ptr_table_store(PL_ptr_table, &proto_perl->Isv_no, &PL_sv_no);
+ ptr_table_store(PL_ptr_table, &proto_perl->Isv_zero, &PL_sv_zero);
ptr_table_store(PL_ptr_table, &proto_perl->Isv_yes, &PL_sv_yes);
ptr_table_store(PL_ptr_table, &proto_perl->Ipadname_const,
&PL_padname_const);
@@ -15914,6 +15915,12 @@ Perl_init_constants(pTHX)
|SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
|SVp_POK|SVf_POK;
+ SvANY(&PL_sv_zero) = new_XPVNV();
+ SvREFCNT(&PL_sv_zero) = SvREFCNT_IMMORTAL;
+ SvFLAGS(&PL_sv_zero) = SVt_PVNV|SVf_READONLY|SVf_PROTECT
+ |SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
+ |SVp_POK|SVf_POK;
+
SvPV_set(&PL_sv_no, (char*)PL_No);
SvCUR_set(&PL_sv_no, 0);
SvLEN_set(&PL_sv_no, 0);
@@ -15926,6 +15933,12 @@ Perl_init_constants(pTHX)
SvIV_set(&PL_sv_yes, 1);
SvNV_set(&PL_sv_yes, 1);
+ SvPV_set(&PL_sv_zero, (char*)PL_Zero);
+ SvCUR_set(&PL_sv_zero, 1);
+ SvLEN_set(&PL_sv_zero, 0);
+ SvIV_set(&PL_sv_zero, 0);
+ SvNV_set(&PL_sv_zero, 0);
+
PadnamePV(&PL_padname_const) = (char *)PL_No;
}
diff --git a/sv.h b/sv.h
index 71c494b367..5b11c18f33 100644
--- a/sv.h
+++ b/sv.h
@@ -2087,7 +2087,7 @@ properly null terminated. Equivalent to sv_setpvs(""), but more efficient.
#define SvPEEK(sv) ""
#endif
-#define SvIMMORTAL(sv) (SvREADONLY(sv) && ((sv)==&PL_sv_undef || (sv)==&PL_sv_yes || (sv)==&PL_sv_no || (sv)==&PL_sv_placeholder))
+#define SvIMMORTAL(sv) (SvREADONLY(sv) && ((sv)==&PL_sv_undef || (sv)==&PL_sv_yes || (sv)==&PL_sv_no || (sv)==&PL_sv_zero || (sv)==&PL_sv_placeholder))
#ifdef DEBUGGING
/* exercise the immortal resurrection code in sv_free2() */