summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2009-05-18 16:12:21 +0100
committerNicholas Clark <nick@ccl4.org>2009-05-18 16:12:21 +0100
commit538f2e763fb7d8e8be3faeafc31371e06e22ce2b (patch)
tree9da298b8a01722bd1130b88ffd69578578258831
parentefc36d52fb6a79de18cc6fc155712ba20b7d0414 (diff)
downloadperl-538f2e763fb7d8e8be3faeafc31371e06e22ce2b.tar.gz
Add S_sv_dup_inc_multiple(), used in place of loops that call sv_dup_inc().
Just 4 uses already give a size saving with gcc -Os.
-rw-r--r--embed.fnc4
-rw-r--r--embed.h10
-rw-r--r--proto.h9
-rw-r--r--sv.c35
4 files changed, 47 insertions, 11 deletions
diff --git a/embed.fnc b/embed.fnc
index 6cda6ce0c8..5f02822816 100644
--- 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 605cf2274a..e320dc5654 100644
--- a/embed.h
+++ b/embed.h
@@ -1125,6 +1125,11 @@
#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
@@ -3454,6 +3459,11 @@
#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 8e177f02d0..3f95eb5d71 100644
--- 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 9c38fcef8c..c7468ecd80 100644
--- 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;