Commit 2af6430c2b for perl
commit 2af6430c2b73cbd5ab2f627b65659a54d5371f97
Author: Paul Evans <leonerd@leonerd.org.uk>
Date: Wed Nov 11 14:39:33 2026 +0000
pp_rv2{av,hv}: Make use of PL_sv_zero
This makes these two ops use the same optimisation that `pp_padav` uses
to avoid creating a zero temporary when asked for a package array or
hash in scalar context. By reusing `PL_sv_zero` we save memory churn in
creating a temporary just to set its value to zero.
As a side-effect of the way it is implemented, we also get this
behaviour for free from `pp_padhv`.
diff --git a/pp_hot.c b/pp_hot.c
index bf0ab509de..5e27b6f62d 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2312,13 +2312,14 @@ S_padhv_rv2hv_common(pTHX_ HV *hv, U8 gimme, bool is_keys, bool has_targ)
}
else {
push_i:
- if (has_targ) {
+ if (!i)
+ rpp_push_IMM(&PL_sv_zero);
+ else if (has_targ) {
dTARGET;
TARGi(i,1);
rpp_push_1(targ);
}
- else
- if (is_keys) {
+ else if (is_keys) {
/* parent op should be an unused OP_KEYS whose targ we can
* use */
dTARG;
@@ -2509,8 +2510,10 @@ PP(pp_rv2av)
if (gimme == G_SCALAR) {
const SSize_t maxarg = AvFILL(av) + 1;
- if (PL_op->op_private & OPpTRUEBOOL)
- rpp_replace_1_IMM_NN(maxarg ? &PL_sv_yes : &PL_sv_zero);
+ if (!maxarg)
+ rpp_replace_1_IMM_NN(&PL_sv_zero);
+ else if (PL_op->op_private & OPpTRUEBOOL)
+ rpp_replace_1_IMM_NN(&PL_sv_yes);
else {
dTARGET;
TARGi(maxarg, 1);
diff --git a/t/op/svflags.t b/t/op/svflags.t
index 703ea6d26b..91cfbd2047 100644
--- a/t/op/svflags.t
+++ b/t/op/svflags.t
@@ -10,7 +10,7 @@ BEGIN {
# Tests the new documented mechanism for determining the original type
# of an SV.
-plan tests => 24;
+plan tests => 27;
use strict;
use B qw(svref_2object SVf_IOK SVf_NOK SVf_POK);
@@ -123,8 +123,34 @@ CODE
unlike($got, qr/Conditional jump or move depends on uninitialised value/,
'All fields initialized in SVt_PV[IV|NV|MG] copies');
-my @arr;
-# pp_padav pushes $PL_sv_zero to the stack here
-my $sc = scalar @arr;
-$xobj = svref_2object(\$sc);
-is($xobj->FLAGS & (SVf_IOK | SVf_POK), SVf_IOK, "PL_sv_zero behaves as number (not string) first");
+# pp_padav returns PL_sv_zero if count=0
+{
+ my @arr;
+ my $sc = scalar @arr;
+ $xobj = svref_2object(\$sc);
+ is($xobj->FLAGS & (SVf_IOK | SVf_POK), SVf_IOK, "PL_sv_zero from pp_padav behaves as number (not string) first");
+}
+
+# pp_padhv returns PL_sv_zero if count=0
+{
+ my %hash;
+ my $sc = scalar %hash;
+ $xobj = svref_2object(\$sc);
+ is($xobj->FLAGS & (SVf_IOK | SVf_POK), SVf_IOK, "PL_sv_zero from pp_padhv behaves as number (not string) first");
+}
+
+# pp_rv2av returns PL_sv_zero if count=0
+{
+ our @pkgarr;
+ my $sc = scalar @pkgarr;
+ $xobj = svref_2object(\$sc);
+ is($xobj->FLAGS & (SVf_IOK | SVf_POK), SVf_IOK, "PL_sv_zero from pp_rv2av behaves as number (not string) first");
+}
+
+# pp_rv2hv returns PL_sv_zero if count=0
+{
+ our %pkghash;
+ my $sc = scalar %pkghash;
+ $xobj = svref_2object(\$sc);
+ is($xobj->FLAGS & (SVf_IOK | SVf_POK), SVf_IOK, "PL_sv_zero from pp_rv2hv behaves as number (not string) first");
+}