add a small buffer to gv_stash_name
authorNicolas R <atoomic@cpan.org>
Thu, 27 Apr 2017 17:29:48 +0000 (11:29 -0600)
committerTony Cook <tony@develop-help.com>
Mon, 4 Sep 2017 23:37:44 +0000 (09:37 +1000)
gv.c

diff --git a/gv.c b/gv.c
index 4bb534b..cfe4be5 100644 (file)
--- a/gv.c
+++ b/gv.c
@@ -1595,10 +1595,11 @@ S_parse_gv_stash_name(pTHX_ HV **stash, GV **gv, const char **name,
                STRLEN *len, const char *nambeg, STRLEN full_len,
                const U32 is_utf8, const I32 add)
 {
-    char *tmpbuf = NULL;
+    char *tmpfullbuf = NULL; /* only malloc one big chunk of memory when the smallbuff is not large enough */
     const char *name_cursor;
     const char *const name_end = nambeg + full_len;
     const char *const name_em1 = name_end - 1;
+    char smallbuf[64]; /* small buffer to avoid a malloc when possible */
 
     PERL_ARGS_ASSERT_PARSE_GV_STASH_NAME;
     
@@ -1629,8 +1630,16 @@ S_parse_gv_stash_name(pTHX_ HV **stash, GV **gv, const char **name,
                     *len += 2;
                 }
                 else { /* using ' for package separator */
-                    if (tmpbuf == NULL) /* only malloc&free once, a little more than needed */
-                        Newx(tmpbuf, full_len+2, char);
+                    /* use our pre-allocated buffer when possible to save a malloc */
+                    char *tmpbuf;
+                    if ( *len+2 <= sizeof smallbuf)
+                        tmpbuf = smallbuf;
+                    else {
+                        /* only malloc once if needed */
+                        if (tmpfullbuf == NULL) /* only malloc&free once, a little more than needed */
+                            Newx(tmpfullbuf, full_len+2, char);
+                        tmpbuf = tmpfullbuf;
+                    }
                     Copy(*name, tmpbuf, *len, char);
                     tmpbuf[(*len)++] = ':';
                     tmpbuf[(*len)++] = ':';
@@ -1639,7 +1648,7 @@ S_parse_gv_stash_name(pTHX_ HV **stash, GV **gv, const char **name,
                 gvp = (GV**)hv_fetch(*stash, key, is_utf8 ? -((I32)*len) : (I32)*len, add);
                 *gv = gvp ? *gvp : NULL;
                 if (!*gv || *gv == (const GV *)&PL_sv_undef) {
-                    Safefree(tmpbuf);
+                    Safefree(tmpfullbuf); /* free our tmpfullbuf if it was used */
                     return FALSE;
                 }
                 /* here we know that *gv && *gv != &PL_sv_undef */
@@ -1681,7 +1690,7 @@ S_parse_gv_stash_name(pTHX_ HV **stash, GV **gv, const char **name,
                            MUTABLE_HV(SvREFCNT_inc_simple(PL_defstash));
                    }
                }
-                Safefree(tmpbuf);
+                Safefree(tmpfullbuf); /* free our tmpfullbuf if it was used */
                 return TRUE;
             }
         }