summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2017-07-17 16:33:38 +0100
committerDavid Mitchell <davem@iabyn.com>2017-07-27 11:30:24 +0100
commite84e4286916d8a219c8a63468807b41df9cde7fe (patch)
treecd426bb11f4713d71bdd6a8cf8ac051c96fc03e5
parentaa36782f823c559475544c99a66db74997ce1edf (diff)
downloadperl-e84e4286916d8a219c8a63468807b41df9cde7fe.tar.gz
Give OP_RV2HV a targ
OP_RV2AV already has one; its not clear why OP_RV2HV didn't. Having one means that in scalar context it can return an int value without having to create a mortal. Ditto when its doing 'keys %h' via OPpRV2HV_ISKEYS.
-rw-r--r--ext/B/t/f_map.t28
-rw-r--r--ext/B/t/f_sort.t4
-rw-r--r--ext/B/t/optree_samples.t8
-rw-r--r--opcode.h2
-rw-r--r--pp_hot.c18
-rw-r--r--regen/opcodes2
6 files changed, 36 insertions, 26 deletions
diff --git a/ext/B/t/f_map.t b/ext/B/t/f_map.t
index 96cea4a495..221f2926e2 100644
--- a/ext/B/t/f_map.t
+++ b/ext/B/t/f_map.t
@@ -108,7 +108,7 @@ checkOptree(note => q{},
# goto 7
# g <0> pushmark s
# h <#> gv[*hash] s
-# i <1> rv2hv lKRM*
+# i <1> rv2hv[t2] lKRM*
# j <2> aassign[t10] KS/COM_AGG
# k <1> leavesub[1 ref] K/REFC,1
EOT_EOT
@@ -130,7 +130,7 @@ EOT_EOT
# goto 7
# g <0> pushmark s
# h <$> gv(*hash) s
-# i <1> rv2hv lKRM*
+# i <1> rv2hv[t1] lKRM*
# j <2> aassign[t5] KS/COM_AGG
# k <1> leavesub[1 ref] K/REFC,1
EONT_EONT
@@ -157,7 +157,7 @@ checkOptree(note => q{},
# 4 <0> pushmark s
# 5 <0> pushmark s
# 6 <#> gv[*hash] s
-# 7 <1> rv2hv lKRM*
+# 7 <1> rv2hv[t2] lKRM*
# 8 <2> aassign[t3] vKS
# 9 <;> nextstate(main 476 (eval 10):1) v:{
# a <0> pushmark sM
@@ -190,7 +190,7 @@ EOT_EOT
# 4 <0> pushmark s
# 5 <0> pushmark s
# 6 <$> gv(*hash) s
-# 7 <1> rv2hv lKRM*
+# 7 <1> rv2hv[t1] lKRM*
# 8 <2> aassign[t2] vKS
# 9 <;> nextstate(main 560 (eval 15):1) v:{
# a <0> pushmark sM
@@ -243,7 +243,7 @@ checkOptree(note => q{},
# goto 7
# b <0> pushmark s
# c <#> gv[*hash] s
-# d <1> rv2hv lKRM*
+# d <1> rv2hv[t2] lKRM*
# e <2> aassign[t10] KS/COM_AGG
# f <1> leavesub[1 ref] K/REFC,1
EOT_EOT
@@ -260,7 +260,7 @@ EOT_EOT
# goto 7
# b <0> pushmark s
# c <$> gv(*hash) s
-# d <1> rv2hv lKRM*
+# d <1> rv2hv[t1] lKRM*
# e <2> aassign[t6] KS/COM_AGG
# f <1> leavesub[1 ref] K/REFC,1
EONT_EONT
@@ -289,7 +289,7 @@ checkOptree(note => q{},
# goto 7
# b <0> pushmark s
# c <#> gv[*hash] s
-# d <1> rv2hv lKRM*
+# d <1> rv2hv[t2] lKRM*
# e <2> aassign[t10] KS/COM_AGG
# f <1> leavesub[1 ref] K/REFC,1
EOT_EOT
@@ -306,7 +306,7 @@ EOT_EOT
# goto 7
# b <0> pushmark s
# c <$> gv(*hash) s
-# d <1> rv2hv lKRM*
+# d <1> rv2hv[t1] lKRM*
# e <2> aassign[t6] KS/COM_AGG
# f <1> leavesub[1 ref] K/REFC,1
EONT_EONT
@@ -335,7 +335,7 @@ checkOptree(note => q{},
# goto 7
# b <0> pushmark s
# c <#> gv[*hash] s
-# d <1> rv2hv lKRM*
+# d <1> rv2hv[t2] lKRM*
# e <2> aassign[t9] KS/COM_AGG
# f <1> leavesub[1 ref] K/REFC,1
EOT_EOT
@@ -352,7 +352,7 @@ EOT_EOT
# goto 7
# b <0> pushmark s
# c <$> gv(*hash) s
-# d <1> rv2hv lKRM*
+# d <1> rv2hv[t1] lKRM*
# e <2> aassign[t5] KS/COM_AGG
# f <1> leavesub[1 ref] K/REFC,1
EONT_EONT
@@ -381,7 +381,7 @@ checkOptree(note => q{},
# goto 7
# b <0> pushmark s
# c <#> gv[*hash] s
-# d <1> rv2hv lKRM*
+# d <1> rv2hv[t2] lKRM*
# e <2> aassign[t8] KS/COM_AGG
# f <1> leavesub[1 ref] K/REFC,1
EOT_EOT
@@ -398,7 +398,7 @@ EOT_EOT
# goto 7
# b <0> pushmark s
# c <$> gv(*hash) s
-# d <1> rv2hv lKRM*
+# d <1> rv2hv[t1] lKRM*
# e <2> aassign[t5] KS/COM_AGG
# f <1> leavesub[1 ref] K/REFC,1
EONT_EONT
@@ -426,7 +426,7 @@ checkOptree(note => q{},
# goto 7
# a <0> pushmark s
# b <#> gv[*hash] s
-# c <1> rv2hv lKRM*
+# c <1> rv2hv[t2] lKRM*
# d <2> aassign[t6] KS/COM_AGG
# e <#> gv[*array] s
# f <1> rv2av[t8] K/1
@@ -445,7 +445,7 @@ EOT_EOT
# goto 7
# a <0> pushmark s
# b <$> gv(*hash) s
-# c <1> rv2hv lKRM*
+# c <1> rv2hv[t1] lKRM*
# d <2> aassign[t4] KS/COM_AGG
# e <$> gv(*array) s
# f <1> rv2av[t5] K/1
diff --git a/ext/B/t/f_sort.t b/ext/B/t/f_sort.t
index 800281fa73..45dcd93ed5 100644
--- a/ext/B/t/f_sort.t
+++ b/ext/B/t/f_sort.t
@@ -280,7 +280,7 @@ checkOptree(note => q{},
# 2 <0> pushmark s
# 3 <0> pushmark s
# 4 <#> gv[*age] s
-# 5 <1> rv2hv lKRM
+# 5 <1> rv2hv[t9] lKRM
# 6 <1> keys[t10] lK/1 < 5.019002
# 6 <1> keys[t10] lKM/1 >=5.019002
# 7 <@> sort lKS*
@@ -294,7 +294,7 @@ EOT_EOT
# 2 <0> pushmark s
# 3 <0> pushmark s
# 4 <$> gv(*age) s
-# 5 <1> rv2hv lKRM
+# 5 <1> rv2hv[t3] lKRM
# 6 <1> keys[t4] lK/1 < 5.019002
# 6 <1> keys[t4] lKM/1 >=5.019002
# 7 <@> sort lKS*
diff --git a/ext/B/t/optree_samples.t b/ext/B/t/optree_samples.t
index 121fd3eec9..7374626663 100644
--- a/ext/B/t/optree_samples.t
+++ b/ext/B/t/optree_samples.t
@@ -483,7 +483,7 @@ checkOptree ( name => '%h = map { getkey($_) => $_ } @a',
# goto 7
# g <0> pushmark s
# h <#> gv[*h] s
-# i <1> rv2hv lKRM*
+# i <1> rv2hv[t2] lKRM*
# j <2> aassign[t10] KS/COM_AGG
# k <1> leavesub[1 ref] K/REFC,1
EOT_EOT
@@ -506,7 +506,7 @@ EOT_EOT
# goto 7
# g <0> pushmark s
# h <$> gv(*h) s
-# i <1> rv2hv lKRM*
+# i <1> rv2hv[t1] lKRM*
# j <2> aassign[t5] KS/COM_AGG
# k <1> leavesub[1 ref] K/REFC,1
EONT_EONT
@@ -519,7 +519,7 @@ checkOptree ( name => '%h=(); for $_(@a){$h{getkey($_)} = $_}',
# 2 <0> pushmark s
# 3 <0> pushmark s
# 4 <#> gv[*h] s
-# 5 <1> rv2hv lKRM*
+# 5 <1> rv2hv[t2] lKRM*
# 6 <2> aassign[t3] vKS
# 7 <;> nextstate(main 506 (eval 24):1) v:{
# 8 <0> pushmark sM
@@ -549,7 +549,7 @@ EOT_EOT
# 2 <0> pushmark s
# 3 <0> pushmark s
# 4 <$> gv(*h) s
-# 5 <1> rv2hv lKRM*
+# 5 <1> rv2hv[t1] lKRM*
# 6 <2> aassign[t2] vKS
# 7 <;> nextstate(main 506 (eval 24):1) v:{
# 8 <0> pushmark sM
diff --git a/opcode.h b/opcode.h
index 77e61e793d..23595c14f5 100644
--- a/opcode.h
+++ b/opcode.h
@@ -1938,7 +1938,7 @@ EXTCONST U32 PL_opargs[] = {
0x00004b08, /* keys */
0x00001b00, /* delete */
0x00001b04, /* exists */
- 0x00000140, /* rv2hv */
+ 0x00000148, /* rv2hv */
0x00014204, /* helem */
0x00024401, /* hslice */
0x00024401, /* kvhslice */
diff --git a/pp_hot.c b/pp_hot.c
index 72cfbb4cd2..67729690b9 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -969,10 +969,13 @@ PP(pp_print)
/* do the common parts of pp_padhv() and pp_rv2hv()
* It assumes the caller has done EXTEND(SP, 1) or equivalent.
* 'is_keys' indicates the OPpPADHV_ISKEYS/OPpRV2HV_ISKEYS flag is set
+ * 'has_targ' indicates that the op has a target - this should
+ * be a compile-time constant so that the code can constant-folded as
+ * appropriate
* */
PERL_STATIC_INLINE OP*
-S_padhv_rv2hv_common(pTHX_ HV *hv, U8 gimme, bool is_keys)
+S_padhv_rv2hv_common(pTHX_ HV *hv, U8 gimme, bool is_keys, bool has_targ)
{
bool tied;
dSP;
@@ -1008,7 +1011,12 @@ S_padhv_rv2hv_common(pTHX_ HV *hv, U8 gimme, bool is_keys)
}
else
i = HvUSEDKEYS(hv);
- mPUSHi(i);
+ if (has_targ) {
+ dTARGET;
+ PUSHi(i);
+ }
+ else
+ mPUSHi(i);
}
else
PUSHs(Perl_hv_scalar(aTHX_ hv));
@@ -1109,7 +1117,8 @@ PP(pp_padhv)
gimme = GIMME_V;
return S_padhv_rv2hv_common(aTHX_ (HV*)TARG, gimme,
- cBOOL(PL_op->op_private & OPpPADHV_ISKEYS));
+ cBOOL(PL_op->op_private & OPpPADHV_ISKEYS),
+ 0 /* has_targ*/);
}
@@ -1191,7 +1200,8 @@ PP(pp_rv2av)
else {
SP--; PUTBACK;
return S_padhv_rv2hv_common(aTHX_ (HV*)sv, gimme,
- cBOOL(PL_op->op_private & OPpRV2HV_ISKEYS));
+ cBOOL(PL_op->op_private & OPpRV2HV_ISKEYS),
+ 1 /* has_targ*/);
}
RETURN;
diff --git a/regen/opcodes b/regen/opcodes
index 58d08c3f3c..137a44f6b9 100644
--- a/regen/opcodes
+++ b/regen/opcodes
@@ -238,7 +238,7 @@ values values ck_each dt% H
keys keys ck_each t% H
delete delete ck_delete % S
exists exists ck_exists is% S
-rv2hv hash dereference ck_rvconst d1
+rv2hv hash dereference ck_rvconst dt1
helem hash element ck_null s2 H S
hslice hash slice ck_null m@ H L
kvhslice key/value hash slice ck_null m@ H L