Give OP_RV2HV a targ
authorDavid Mitchell <davem@iabyn.com>
Mon, 17 Jul 2017 15:33:38 +0000 (16:33 +0100)
committerDavid Mitchell <davem@iabyn.com>
Thu, 27 Jul 2017 10:30:24 +0000 (11:30 +0100)
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.

ext/B/t/f_map.t
ext/B/t/f_sort.t
ext/B/t/optree_samples.t
opcode.h
pp_hot.c
regen/opcodes

index 96cea4a..221f292 100644 (file)
@@ -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
index 800281f..45dcd93 100644 (file)
@@ -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*
index 121fd3e..7374626 100644 (file)
@@ -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
index 77e61e7..23595c1 100644 (file)
--- 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 */
index 72cfbb4..6772969 100644 (file)
--- 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;
 
index 58d08c3..137a44f 100644 (file)
@@ -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      d     
+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