This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
S_sv_2iuv_common(): optimise single digit strings
authorDavid Mitchell <davem@iabyn.com>
Tue, 27 Sep 2016 11:59:01 +0000 (12:59 +0100)
committerDavid Mitchell <davem@iabyn.com>
Tue, 27 Sep 2016 12:05:25 +0000 (13:05 +0100)
When converting a POK SV to an IOK SV, short-cut the relatively
common case of a string that is only one char long and consists of a
single digit, e.g. "0". Thus skipping all the floating-point, infinity,
whitespace etc complexity.

sv.c
t/perf/benchmarks

diff --git a/sv.c b/sv.c
index 850c727..088359f 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -2219,7 +2219,24 @@ S_sv_2iuv_common(pTHX_ SV *const sv)
     }
     else if (SvPOKp(sv)) {
        UV value;
-       const int numtype = grok_number(SvPVX_const(sv), SvCUR(sv), &value);
+       int numtype;
+        const char *s = SvPVX_const(sv);
+        const STRLEN cur = SvCUR(sv);
+
+        /* short-cut for a single digit string like "1" */
+
+        if (cur == 1) {
+            char c = *s;
+            if (isDIGIT(c)) {
+                if (SvTYPE(sv) < SVt_PVIV)
+                    sv_upgrade(sv, SVt_PVIV);
+                (void)SvIOK_on(sv);
+                SvIV_set(sv, (IV)(c - '0'));
+                return FALSE;
+            }
+        }
+
+       numtype = grok_number(s, cur, &value);
        /* We want to avoid a possible problem when we cache an IV/ a UV which
           may be later translated to an NV, and the resulting NV is not
           the same as the direct translation of the initial string
index 6ea1ce8..6c15523 100644 (file)
         setup   => 'my ($x,$y); ($x,$y,$z) = (1, 2.2, 3.3);',
         code    => '$z = $x + $y',
     },
+    'expr::arith::add_lex_ss' => {
+        desc    => 'add two short strings and assign to a lexical var',
+        setup   => 'my ($x,$y,$z) = ("1", "2", 1);',
+        code    => '$z = $x + $y; $x = "1"; ',
+    },
+
+    'expr::arith::add_lex_ll' => {
+        desc    => 'add two long strings and assign to a lexical var',
+        setup   => 'my ($x,$y,$z) = ("12345", "23456", 1);',
+        code    => '$z = $x + $y; $x = "12345"; ',
+    },
 
     'expr::arith::sub_lex_ii' => {
         desc    => 'subtract two integers and assign to a lexical var',