Skip to content

Commit f7d9d8b

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 628a2f6 commit f7d9d8b

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
@@ -465,6 +465,9 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
465465
NV value_nv = 0;
466466
const PERL_UINT_FAST8_T base = 1 << shift; /* 2, 8, or 16 */
467467

468+
/* Value above which, the next digit processed would overflow */
469+
UV max_div = UV_MAX >> shift;
470+
468471
for (; s < e; s++) {
469472
if (generic_isCC_(*s, class_bit)) {
470473
/* Write it in this wonky order with a goto to attempt to get the
@@ -473,19 +476,12 @@ Perl_grok_bin_oct_hex(pTHX_ const char * const start,
473476
(khw suspects that adding a LIKELY() just above would do the
474477
same thing) */
475478
redo: ;
476-
477-
/* Make room for the next digit */
478-
UV tentative_value = value << shift;
479-
480-
/* If shiftng back doesn't yield the previous value, it was
481-
* because a bit got shifted off the left end, so overflowed.
482-
* But if it worked, add the new digit. */
483-
if (LIKELY((tentative_value >> shift) == value)) {
479+
if (LIKELY(value <= max_div)) {
484480
/* Note XDIGIT_VALUE() is branchless, works on binary and
485481
* octal as well, so can be used here, without noticeably
486482
* slowing those down (it does have unnecessary shifts, ANDSs,
487483
* and additions for those) */
488-
value = tentative_value | XDIGIT_VALUE(*s);
484+
value = (value << shift) | XDIGIT_VALUE(*s);
489485
factor *= base;
490486
continue;
491487
}

0 commit comments

Comments
 (0)