summaryrefslogtreecommitdiff
path: root/numeric.c
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2020-01-16 11:57:04 -0700
committerKarl Williamson <khw@cpan.org>2020-01-18 22:07:04 -0700
commitb2fffc9a07e8b6f34b2e6cb858be3b8cc06dcd6e (patch)
tree0daf9c27d6e27418c1380106098a27f6ee43a709 /numeric.c
parent44aeaa422369a68896061189a0c331c38e873cc1 (diff)
downloadperl-b2fffc9a07e8b6f34b2e6cb858be3b8cc06dcd6e.tar.gz
grok_bin_oct_hex: Unroll loop one more iteration
Earlier I was confused when I thought that 7 hex digits were the max before we needed to start worrying about overflow. That's true for signed results where everything above 7FFF_FFFF won't fit in a 32-bit signed integer. But these functions return unsigned, and so any 8 digits will fit in a 32-bit word.
Diffstat (limited to 'numeric.c')
-rw-r--r--numeric.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/numeric.c b/numeric.c
index 6e5bce73e2..58f5a085bc 100644
--- a/numeric.c
+++ b/numeric.c
@@ -423,9 +423,8 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
s = s0; /* s0 potentially advanced from 'start' */
- /* Unroll the loop so that the first 7 digits are branchless except for the
- * switch. An eighth one could overflow a 32 bit word. This should
- * completely handle the common case without needing extra checks */
+ /* Unroll the loop so that the first 8 digits are branchless except for the
+ * switch. A ninth one overflows a 32 bit word. */
switch (len) {
case 0:
return 0;
@@ -434,6 +433,11 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
value = (value << shift) | XDIGIT_VALUE(*s);
s++;
/* FALLTHROUGH */
+ case 7:
+ if (! _generic_isCC(*s, class_bit)) break;
+ value = (value << shift) | XDIGIT_VALUE(*s);
+ s++;
+ /* FALLTHROUGH */
case 6:
if (! _generic_isCC(*s, class_bit)) break;
value = (value << shift) | XDIGIT_VALUE(*s);
@@ -463,7 +467,7 @@ Perl_grok_bin_oct_hex(pTHX_ const char *start,
if (! _generic_isCC(*s, class_bit)) break;
value = (value << shift) | XDIGIT_VALUE(*s);
- if (LIKELY(len <= 7)) {
+ if (LIKELY(len <= 8)) {
return value;
}