Skip to content

Commit 901167d

Browse files
committed
grok_bin_oct_dec: Speed up overflow detection
We can compute outside the loop the exact value at which the next iteration wil overflow, saving some operations
1 parent 314303b commit 901167d

File tree

1 file changed

+5
-9
lines changed

1 file changed

+5
-9
lines changed

numeric.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,9 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
495495
NV value_nv = 0;
496496
const PERL_UINT_FAST8_T base = 1 << shift; /* 2, 8, or 16 */
497497

498+
/* Value above which, the next digit processed would overflow */
499+
UV max_div = UV_MAX >> shift;
500+
498501
for (; s < e; s++) {
499502
if (generic_isCC_(*s, class_bit)) {
500503
/* Write it in this wonky order with a goto to attempt to get the
@@ -503,19 +506,12 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
503506
(khw suspects that adding a LIKELY() just above would do the
504507
same thing) */
505508
redo: ;
506-
507-
/* Make room for the next digit */
508-
UV tentative_value = value << shift;
509-
510-
/* If shiftng back doesn't yield the previous value, it was
511-
* because a bit got shifted off the left end, so overflowed.
512-
* But if it worked, add the new digit. */
513-
if (LIKELY((tentative_value >> shift) == value)) {
509+
if (LIKELY(value <= max_div)) {
514510
/* Note XDIGIT_VALUE() is branchless, works on binary and
515511
* octal as well, so can be used here, without noticeably
516512
* slowing those down (it does have unnecessary shifts, ANDSs,
517513
* and additions for those) */
518-
value = tentative_value | XDIGIT_VALUE(*s);
514+
value = (value << shift) | XDIGIT_VALUE(*s);
519515
factor *= base;
520516
continue;
521517
}

0 commit comments

Comments
 (0)