Add S_sv_dup_inc_multiple(), used in place of loops that call sv_dup_inc().
Nicholas Clark [Mon, 18 May 2009 15:12:21 +0000 (16:12 +0100)]
Just 4 uses already give a size saving with gcc -Os.

embed.fnc
embed.h
proto.h
sv.c

index 6cda6ce..5f02822 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -1290,6 +1290,10 @@ Ap       |PerlIO*|fp_dup         |NULLOK PerlIO *const fp|const char type|NN CLONE_PARAMS *co
 ApR    |DIR*   |dirp_dup       |NULLOK DIR *const dp
 ApR    |GP*    |gp_dup         |NULLOK GP *const gp|NN CLONE_PARAMS *const param
 ApR    |MAGIC* |mg_dup         |NULLOK MAGIC *mg|NN CLONE_PARAMS *const param
+#if defined(PERL_IN_SV_C) || defined(PERL_DECL_PROT)
+s      |SV **  |sv_dup_inc_multiple|NN SV *const *source|NN SV **dest \
+                               |SSize_t items|NN CLONE_PARAMS *const param
+#endif
 ApR    |SV*    |sv_dup         |NULLOK const SV *const sstr|NN CLONE_PARAMS *const param
 Ap     |void   |rvpv_dup       |NN SV *const dstr|NN const SV *const sstr|NN CLONE_PARAMS *const param
 Ap     |yy_parser*|parser_dup  |NULLOK const yy_parser *const proto|NN CLONE_PARAMS *const param
diff --git a/embed.h b/embed.h
index 605cf22..e320dc5 100644 (file)
--- a/embed.h
+++ b/embed.h
 #define dirp_dup               Perl_dirp_dup
 #define gp_dup                 Perl_gp_dup
 #define mg_dup                 Perl_mg_dup
+#if defined(PERL_IN_SV_C) || defined(PERL_DECL_PROT)
+#ifdef PERL_CORE
+#define sv_dup_inc_multiple    S_sv_dup_inc_multiple
+#endif
+#endif
 #define sv_dup                 Perl_sv_dup
 #define rvpv_dup               Perl_rvpv_dup
 #define parser_dup             Perl_parser_dup
 #define dirp_dup(a)            Perl_dirp_dup(aTHX_ a)
 #define gp_dup(a,b)            Perl_gp_dup(aTHX_ a,b)
 #define mg_dup(a,b)            Perl_mg_dup(aTHX_ a,b)
+#if defined(PERL_IN_SV_C) || defined(PERL_DECL_PROT)
+#ifdef PERL_CORE
+#define sv_dup_inc_multiple(a,b,c,d)   S_sv_dup_inc_multiple(aTHX_ a,b,c,d)
+#endif
+#endif
 #define sv_dup(a,b)            Perl_sv_dup(aTHX_ a,b)
 #define rvpv_dup(a,b,c)                Perl_rvpv_dup(aTHX_ a,b,c)
 #define parser_dup(a,b)                Perl_parser_dup(aTHX_ a,b)
diff --git a/proto.h b/proto.h
index 8e177f0..3f95eb5 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -4089,6 +4089,15 @@ PERL_CALLCONV MAGIC*     Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *const param)
 #define PERL_ARGS_ASSERT_MG_DUP        \
        assert(param)
 
+#if defined(PERL_IN_SV_C) || defined(PERL_DECL_PROT)
+STATIC SV **   S_sv_dup_inc_multiple(pTHX_ SV *const *source, SV **dest, SSize_t items, CLONE_PARAMS *const param)
+                       __attribute__nonnull__(pTHX_1)
+                       __attribute__nonnull__(pTHX_2)
+                       __attribute__nonnull__(pTHX_4);
+#define PERL_ARGS_ASSERT_SV_DUP_INC_MULTIPLE   \
+       assert(source); assert(dest); assert(param)
+
+#endif
 PERL_CALLCONV SV*      Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                        __attribute__warn_unused_result__
                        __attribute__nonnull__(pTHX_2);
diff --git a/sv.c b/sv.c
index 9c38fce..c7468ec 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -10297,7 +10297,8 @@ ptr_table_* functions.
 
 /* Certain cases in Perl_ss_dup have been merged, by relying on the fact
    that currently av_dup, gv_dup and hv_dup are the same as sv_dup.
-   If this changes, please unmerge ss_dup.  */
+   If this changes, please unmerge ss_dup.
+   Likewise, sv_dup_inc_multiple() relies on this fact.  */
 #define sv_dup_inc(s,t)        SvREFCNT_inc(sv_dup(s,t))
 #define sv_dup_inc_NN(s,t)     SvREFCNT_inc_NN(sv_dup(s,t))
 #define av_dup(s,t)    MUTABLE_AV(sv_dup((const SV *)s,t))
@@ -10552,10 +10553,8 @@ Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *const param)
                        AMT_AMAGIC((AMT*)nmg->mg_ptr))
                {
                    AMT * const namtp = (AMT*)nmg->mg_ptr;
-                   I32 i;
-                   for (i = 1; i < NofAMmeth; i++) {
-                       namtp->table[i] = cv_dup_inc(namtp->table[i], param);
-                   }
+                   sv_dup_inc_multiple((SV**)(namtp->table),
+                                       (SV**)(namtp->table), NofAMmeth, param);
                }
            }
            else if (nmg->mg_len == HEf_SVKEY)
@@ -10771,6 +10770,20 @@ Perl_rvpv_dup(pTHX_ SV *const dstr, const SV *const sstr, CLONE_PARAMS *const pa
     }
 }
 
+/* duplicate a list of SVs. source and dest may point to the same memory.  */
+static SV **
+S_sv_dup_inc_multiple(pTHX_ SV *const *source, SV **dest,
+                     SSize_t items, CLONE_PARAMS *const param)
+{
+    PERL_ARGS_ASSERT_SV_DUP_INC_MULTIPLE;
+
+    while (items-- > 0) {
+       *dest++ = sv_dup_inc(*source++, param);
+    }
+
+    return dest;
+}
+
 /* duplicate an SV of any type (including AV, HV etc) */
 
 SV *
@@ -10994,8 +11007,8 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                    AvARRAY(MUTABLE_AV(dstr)) = dst_ary;
                    AvALLOC((const AV *)dstr) = dst_ary;
                    if (AvREAL((const AV *)sstr)) {
-                       while (items-- > 0)
-                           *dst_ary++ = sv_dup_inc(*src_ary++, param);
+                       dst_ary = sv_dup_inc_multiple(src_ary, dst_ary, items,
+                                                     param);
                    }
                    else {
                        while (items-- > 0)
@@ -12175,10 +12188,10 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     if (proto_perl->Ipsig_ptr) {
        Newx(PL_psig_ptr,  SIG_SIZE, SV*);
        Newx(PL_psig_name, SIG_SIZE, SV*);
-       for (i = 1; i < SIG_SIZE; i++) {
-           PL_psig_ptr[i]  = sv_dup_inc(proto_perl->Ipsig_ptr[i], param);
-           PL_psig_name[i] = sv_dup_inc(proto_perl->Ipsig_name[i], param);
-       }
+       sv_dup_inc_multiple(proto_perl->Ipsig_ptr, PL_psig_ptr, SIG_SIZE,
+                           param);
+       sv_dup_inc_multiple(proto_perl->Ipsig_name, PL_psig_name, SIG_SIZE,
+                           param);
     }
     else {
        PL_psig_ptr     = (SV**)NULL;