Encourage compilers to tail call optimise in sv_savepv, sv_savepvn
Nicholas Clark [Fri, 16 Jul 2004 11:04:37 +0000 (11:04 +0000)]
and sv_savesharedpv. Need to create non-void returning versions of
Copy and Zero, as the existing macros deliberately cast to (void)

p4raw-id: //depot/perl@23126

handy.h
malloc.c
perl.c
pod/perlapi.pod
sv.c
util.c

diff --git a/handy.h b/handy.h
index 19a5934..e5c7c45 100644 (file)
--- a/handy.h
+++ b/handy.h
@@ -559,16 +559,30 @@ The XSUB-writer's interface to the C C<memmove> function.  The C<src> is the
 source, C<dest> is the destination, C<nitems> is the number of items, and C<type> is
 the type.  Can do overlapping moves.  See also C<Copy>.
 
+=for apidoc Am|void *|MoveD|void* src|void* dest|int nitems|type
+Like C<Move> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
 =for apidoc Am|void|Copy|void* src|void* dest|int nitems|type
 The XSUB-writer's interface to the C C<memcpy> function.  The C<src> is the
 source, C<dest> is the destination, C<nitems> is the number of items, and C<type> is
 the type.  May fail on overlapping copies.  See also C<Move>.
 
+=for apidoc Am|void *|CopyD|void* src|void* dest|int nitems|type
+
+Like C<Copy> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
 =for apidoc Am|void|Zero|void* dest|int nitems|type
 
 The XSUB-writer's interface to the C C<memzero> function.  The C<dest> is the
 destination, C<nitems> is the number of items, and C<type> is the type.
 
+=for apidoc Am|void *|ZeroD|void* dest|int nitems|type
+
+Like C<Zero> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
 =for apidoc Am|void|StructCopy|type src|type dest|type
 This is an architecture-independent macro to copy one structure to another.
 
@@ -605,6 +619,15 @@ hopefully catches attempts to access uninitialized memory.
 #define Copy(s,d,n,t)  (MEM_WRAP_CHECK(n,t), (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t)))
 #define Zero(d,n,t)    (MEM_WRAP_CHECK(n,t), (void)memzero((char*)(d), (n) * sizeof(t)))
 
+#define MoveD(s,d,n,t) (MEM_WRAP_CHECK(n,t), memmove((char*)(d),(char*)(s), (n) * sizeof(t)))
+#define CopyD(s,d,n,t) (MEM_WRAP_CHECK(n,t), memcpy((char*)(d),(char*)(s), (n) * sizeof(t)))
+#ifdef HAS_MEMSET
+#define ZeroD(d,n,t)   (MEM_WRAP_CHECK(n,t), memzero((char*)(d), (n) * sizeof(t)))
+#else
+/* Using bzero(), which returns void.  */
+#define ZeroD(d,n,t)   (MEM_WRAP_CHECK(n,t), memzero((char*)(d), (n) * sizeof(t)),d)
+#endif
+
 #define Poison(d,n,t)  (MEM_WRAP_CHECK(n,t), (void)memset((char*)(d), 0xAB, (n) * sizeof(t)))
 
 #else
@@ -627,6 +650,14 @@ hopefully catches attempts to access uninitialized memory.
 #define Copy(s,d,n,t)  (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
 #define Zero(d,n,t)    (void)memzero((char*)(d), (n) * sizeof(t))
 
+#define MoveD(s,d,n,t) memmove((char*)(d),(char*)(s), (n) * sizeof(t))
+#define CopyD(s,d,n,t) memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
+#ifdef HAS_MEMSET
+#define ZeroD(d,n,t)   memzero((char*)(d), (n) * sizeof(t))
+#else
+#define ZeroD(d,n,t)   ((void)memzero((char*)(d), (n) * sizeof(t)),d)
+#endif
+
 #define Poison(d,n,t)  (void)memset((char*)(d), 0xAB, (n) * sizeof(t))
 
 #endif
@@ -640,6 +671,9 @@ hopefully catches attempts to access uninitialized memory.
 #define Move(s,d,n,t)
 #define Copy(s,d,n,t)
 #define Zero(d,n,t)
+#define MoveD(s,d,n,t) d
+#define CopyD(s,d,n,t) d
+#define ZeroD(d,n,t)   d
 #define Poison(d,n,t)
 #define Safefree(d)    (d) = (d)
 
index 6013e40..e5f58e4 100644 (file)
--- a/malloc.c
+++ b/malloc.c
 #      define Free_t void
 #    endif
 #    define Copy(s,d,n,t) (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
+#    define CopyD(s,d,n,t) memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
 #    define PerlEnv_getenv getenv
 #    define PerlIO_printf fprintf
 #    define PerlIO_stderr() stderr
@@ -2311,8 +2312,7 @@ Perl_strdup(const char *s)
     MEM_SIZE l = strlen(s);
     char *s1 = (char *)Perl_malloc(l+1);
 
-    Copy(s, s1, (MEM_SIZE)(l+1), char);
-    return s1;
+    return CopyD(s, s1, (MEM_SIZE)(l+1), char);
 }
 
 #ifdef PERL_CORE
diff --git a/perl.c b/perl.c
index f387cf1..7eb121e 100644 (file)
--- a/perl.c
+++ b/perl.c
@@ -190,8 +190,7 @@ perl_alloc(void)
     my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter));
 
     INIT_TLS_AND_INTERP;
-    Zero(my_perl, 1, PerlInterpreter);
-    return my_perl;
+    return ZeroD(my_perl, 1, PerlInterpreter);
 }
 #endif /* PERL_IMPLICIT_SYS */
 
index 512ee44..fb22429 100644 (file)
@@ -1554,6 +1554,16 @@ the type.  May fail on overlapping copies.  See also C<Move>.
 =for hackers
 Found in file handy.h
 
+=item CopyD
+
+Like C<Copy> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
+       void *  CopyD(void* src, void* dest, int nitems, type)
+
+=for hackers
+Found in file handy.h
+
 =item Move
 
 The XSUB-writer's interface to the C C<memmove> function.  The C<src> is the
@@ -1565,6 +1575,16 @@ the type.  Can do overlapping moves.  See also C<Copy>.
 =for hackers
 Found in file handy.h
 
+=item MoveD
+
+Like C<Move> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
+       void *  MoveD(void* src, void* dest, int nitems, type)
+
+=for hackers
+Found in file handy.h
+
 =item New
 
 The XSUB-writer's interface to the C C<malloc> function.
@@ -1685,6 +1705,16 @@ destination, C<nitems> is the number of items, and C<type> is the type.
 =for hackers
 Found in file handy.h
 
+=item ZeroD
+
+Like C<Zero> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
+       void *  ZeroD(void* dest, int nitems, type)
+
+=for hackers
+Found in file handy.h
+
 
 =back
 
diff --git a/sv.c b/sv.c
index 50501e7..9079315 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3742,9 +3742,8 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
        *lp = len;
        s = SvGROW(sv, len + 1);
        SvCUR_set(sv, len);
-       (void)strcpy(s, t);
        SvPOKp_on(sv);
-       return s;
+       return strcpy(s, t);
     }
 }
 
diff --git a/util.c b/util.c
index 030c706..b3375de 100644 (file)
--- a/util.c
+++ b/util.c
@@ -751,12 +751,12 @@ be freed with the C<Safefree()> function.
 char *
 Perl_savepv(pTHX_ const char *pv)
 {
-    register char *newaddr = Nullch;
-    if (pv) {
-       New(902,newaddr,strlen(pv)+1,char);
-       (void)strcpy(newaddr,pv);
-    }
-    return newaddr;
+    register char *newaddr;
+    if (!pv)
+       return Nullch;
+
+    New(902,newaddr,strlen(pv)+1,char);
+    return strcpy(newaddr,pv);
 }
 
 /* same thing but with a known length */
@@ -780,13 +780,13 @@ Perl_savepvn(pTHX_ const char *pv, register I32 len)
     New(903,newaddr,len+1,char);
     /* Give a meaning to NULL pointer mainly for the use in sv_magic() */
     if (pv) {
-       Copy(pv,newaddr,len,char);      /* might not be null terminated */
-       newaddr[len] = '\0';            /* is now */
+       /* might not be null terminated */
+       newaddr[len] = '\0';
+       return CopyD(pv,newaddr,len,char);
     }
     else {
-       Zero(newaddr,len+1,char);
+       return ZeroD(newaddr,len+1,char);
     }
-    return newaddr;
 }
 
 /*
@@ -800,17 +800,17 @@ which is shared between threads.
 char *
 Perl_savesharedpv(pTHX_ const char *pv)
 {
-    register char *newaddr = Nullch;
-    if (pv) {
-       newaddr = (char*)PerlMemShared_malloc(strlen(pv)+1);
-       if (!newaddr) {
-           PerlLIO_write(PerlIO_fileno(Perl_error_log),
-                         PL_no_mem, strlen(PL_no_mem));
-           my_exit(1);
-       }
-       (void)strcpy(newaddr,pv);
+    register char *newaddr;
+    if (!pv)
+       return Nullch;
+
+    newaddr = (char*)PerlMemShared_malloc(strlen(pv)+1);
+    if (!newaddr) {
+       PerlLIO_write(PerlIO_fileno(Perl_error_log),
+                     PL_no_mem, strlen(PL_no_mem));
+       my_exit(1);
     }
-    return newaddr;
+    return strcpy(newaddr,pv);
 }