diff options
author | Karl Williamson <khw@cpan.org> | 2020-01-16 11:57:04 -0700 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2020-01-18 22:07:04 -0700 |
commit | b2fffc9a07e8b6f34b2e6cb858be3b8cc06dcd6e (patch) | |
tree | 0daf9c27d6e27418c1380106098a27f6ee43a709 | |
parent | 44aeaa422369a68896061189a0c331c38e873cc1 (diff) | |
download | perl-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.
-rw-r--r-- | numeric.c | 12 |
1 files changed, 8 insertions, 4 deletions
@@ -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; } |