add SvREFCNT_dec_NN()
authorDavid Mitchell <davem@iabyn.com>
Tue, 4 Dec 2012 11:32:39 +0000 (11:32 +0000)
committerDavid Mitchell <davem@iabyn.com>
Tue, 4 Dec 2012 11:32:39 +0000 (11:32 +0000)
Like SvREFCNT_dec(), but skips the not null check, making code potentially
smaller and faster.

Also as proof of concept, updates the SvREFCNT_dec's in scope.c where
it's obvious the value can't be NULL. There are still 500+ uses in the
perl core that need evaluating!

inline.h
scope.c
sv.h

index 5e11b69..776a304 100644 (file)
--- a/inline.h
+++ b/inline.h
@@ -64,6 +64,16 @@ S_SvREFCNT_dec(pTHX_ SV *sv)
 }
 
 PERL_STATIC_INLINE void
+S_SvREFCNT_dec_NN(pTHX_ SV *sv)
+{
+    U32 rc = SvREFCNT(sv);
+    if (rc > 1)
+       SvREFCNT(sv) = rc - 1;
+    else
+       Perl_sv_free2(aTHX_ sv, rc);
+}
+
+PERL_STATIC_INLINE void
 SvAMAGIC_on(SV *sv)
 {
     assert(SvROK(sv));
diff --git a/scope.c b/scope.c
index 67fce5c..ab09eff 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -166,7 +166,7 @@ Perl_free_tmps(pTHX)
 #endif
        if (sv && sv != &PL_sv_undef) {
            SvTEMP_off(sv);
-           SvREFCNT_dec(sv);           /* note, can modify tmps_ix!!! */
+           SvREFCNT_dec_NN(sv);                /* note, can modify tmps_ix!!! */
        }
     }
 }
@@ -837,7 +837,7 @@ Perl_leave_scope(pTHX_ I32 base)
                 mg_set(ARG0_SV);
                 PL_localizing = 0;
             }
-           SvREFCNT_dec(ARG0_SV);
+           SvREFCNT_dec_NN(ARG0_SV);
            SvREFCNT_dec(refsv);
            break;
         }
@@ -895,7 +895,7 @@ Perl_leave_scope(pTHX_ I32 base)
                 mg_set(ARG0_SV);
                 PL_localizing = 0;
             }
-           SvREFCNT_dec(ARG1_GV);
+           SvREFCNT_dec_NN(ARG1_GV);
            break;
        case SAVEt_HV:                          /* hash reference */
            SvREFCNT_dec(GvHV(ARG1_GV));
@@ -905,7 +905,7 @@ Perl_leave_scope(pTHX_ I32 base)
                 mg_set(ARG0_SV);
                 PL_localizing = 0;
             }
-           SvREFCNT_dec(ARG1_GV);
+           SvREFCNT_dec_NN(ARG1_GV);
            break;
        case SAVEt_INT_SMALL:
            *(int*)ARG0_PTR = (int)(uv >> SAVE_TIGHT_SHIFT);
@@ -964,7 +964,7 @@ Perl_leave_scope(pTHX_ I32 base)
                     /* putting a method back into circulation ("local")*/      
                     gv_method_changed(ARG1_GV);
            }
-           SvREFCNT_dec(ARG1_GV);
+           SvREFCNT_dec_NN(ARG1_GV);
            break;
         }
        case SAVEt_FREESV:
@@ -1073,7 +1073,7 @@ Perl_leave_scope(pTHX_ I32 base)
                     }
                     default:   *svp = newSV(0);                break;
                     }
-                    SvREFCNT_dec(sv);  /* Cast current value to the winds. */
+                    SvREFCNT_dec_NN(sv); /* Cast current value to the winds. */
                     /* preserve pad nature, but also mark as not live
                      * for any closure capturing */
                     SvFLAGS(*svp) |= (SVs_PADMY|SVs_PADSTALE);
diff --git a/sv.h b/sv.h
index cb5ac62..2576a65 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -286,6 +286,11 @@ and faster.
 =for apidoc Am|void|SvREFCNT_dec|SV* sv
 Decrements the reference count of the given SV.
 
+=for apidoc Am|void|SvREFCNT_dec_NN|SV* sv
+Same as SvREFCNT_dec, but can only be used if you know I<sv>
+is not NULL.  Since we don't have to check the NULLness, it's faster
+and smaller.
+
 =for apidoc Am|svtype|SvTYPE|SV* sv
 Returns the type of the SV.  See C<svtype>.
 
@@ -312,6 +317,7 @@ perform the upgrade if necessary.  See C<svtype>.
 #define SvREFCNT_inc_simple_void_NN(sv)        (void)(++SvREFCNT(MUTABLE_SV(sv)))
 
 #define SvREFCNT_dec(sv)       S_SvREFCNT_dec(aTHX_ MUTABLE_SV(sv))
+#define SvREFCNT_dec_NN(sv)    S_SvREFCNT_dec_NN(aTHX_ MUTABLE_SV(sv))
 
 #define SVTYPEMASK     0xff
 #define SvTYPE(sv)     ((svtype)((sv)->sv_flags & SVTYPEMASK))