In perl.git, the branch blead has been updated <https://perl5.git.perl.org/perl.git/commitdiff/ad9b9a4926e4b0d348c048937df69e382f7e6d27?hp=59592778585db09866cbb37a7ab04eefc07b4df4>
- Log ----------------------------------------------------------------- commit ad9b9a4926e4b0d348c048937df69e382f7e6d27 Author: Tomasz Konojacki <m...@xenu.pl> Date: Wed Nov 21 09:26:31 2018 +0100 optimize IV -> UV conversions This commit replaces all instances of code that looks like this: uv = (iv == IV_MIN) ? (UV)iv : (UV)(-iv) with simpler and more optimal: uv = -(UV)iv While -iv indeed results in an undefined behaviour when iv == IV_MIN, -(UV)iv is perfectly well defined and does the right thing. C standard guarantees that the result of (UV)iv (for negative iv) is equal to iv + UV_MAX + 1 (see 6.3.1.3, paragraph 2 in C11). It also guarantees that the result of -uv is UV_MAX - uv + 1 (6.2.5, paragraph 9). That means that the result of -(UV)iv is UV_MAX - (iv + UV_MAX + 1) + 1 which is equal to -iv for *all* possible negative values of iv. [perl #133677] commit 9ba9a28aaea66bad2de041880a2c4210a911dda6 Author: David Mitchell <da...@iabyn.com> Date: Wed Nov 21 12:09:45 2018 +0000 S_hv_delete_common(): avoid undefined behaviour ASAN -fsanitize-undefined was tripping on the second of these two lines: svp = AvARRAY(isa); end = svp + AvFILLp(isa)+1; In the case where svp is NULL and AvFILLp(isa) is -1, the first addition is undefined behaviour. Add the 1 first, so that it becomes svp + (-1+1), which is safe. ----------------------------------------------------------------------- Summary of changes: hv.c | 2 +- pp.c | 18 +++++++++--------- pp_hot.c | 4 ++-- sv.c | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/hv.c b/hv.c index d3d02d1046..fc90a5146b 100644 --- a/hv.c +++ b/hv.c @@ -1295,7 +1295,7 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen, SV **svp, **end; strip_magic: svp = AvARRAY(isa); - end = svp + AvFILLp(isa)+1; + end = svp + (AvFILLp(isa)+1); while (svp < end) { if (*svp) mg_free_type(*svp, PERL_MAGIC_isaelem); diff --git a/pp.c b/pp.c index 6d432acd31..880f266081 100644 --- a/pp.c +++ b/pp.c @@ -1319,7 +1319,7 @@ PP(pp_multiply) auvok = TRUE; /* effectively it's a UV now */ } else { /* abs, auvok == false records sign */ - alow = (aiv == IV_MIN) ? (UV)aiv : (UV)(-aiv); + alow = -(UV)aiv; } } if (buvok) { @@ -1331,7 +1331,7 @@ PP(pp_multiply) buvok = TRUE; /* effectively it's a UV now */ } else { /* abs, buvok == false records sign */ - blow = (biv == IV_MIN) ? (UV)biv : (UV)(-biv); + blow = -(UV)biv; } } @@ -1462,7 +1462,7 @@ PP(pp_divide) right_non_neg = TRUE; /* effectively it's a UV now */ } else { - right = (biv == IV_MIN) ? (UV)biv : (UV)(-biv); + right = -(UV)biv; } } /* historically undef()/0 gives a "Use of uninitialized value" @@ -1483,7 +1483,7 @@ PP(pp_divide) left_non_neg = TRUE; /* effectively it's a UV now */ } else { - left = (aiv == IV_MIN) ? (UV)aiv : (UV)(-aiv); + left = -(UV)aiv; } } @@ -1566,7 +1566,7 @@ PP(pp_modulo) right = biv; right_neg = FALSE; /* effectively it's a UV now */ } else { - right = (biv == IV_MIN) ? (UV)biv : (UV)(-biv); + right = -(UV)biv; } } } @@ -1596,7 +1596,7 @@ PP(pp_modulo) left = aiv; left_neg = FALSE; /* effectively it's a UV now */ } else { - left = (aiv == IV_MIN) ? (UV)aiv : (UV)(-aiv); + left = -(UV)aiv; } } } @@ -1893,8 +1893,8 @@ PP(pp_subtract) if (aiv >= 0) { auv = aiv; auvok = 1; /* Now acting as a sign flag. */ - } else { /* 2s complement assumption for IV_MIN */ - auv = (aiv == IV_MIN) ? (UV)aiv : (UV)-aiv; + } else { + auv = -(UV)aiv; } } a_valid = 1; @@ -1914,7 +1914,7 @@ PP(pp_subtract) buv = biv; buvok = 1; } else - buv = (biv == IV_MIN) ? (UV)biv : (UV)-biv; + buv = -(UV)biv; } /* ?uvok if value is >= 0. basically, flagged as UV if it's +ve, else "IV" now, independent of how it came in. diff --git a/pp_hot.c b/pp_hot.c index dc02612042..ace5f0208b 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -1521,7 +1521,7 @@ PP(pp_add) auv = aiv; auvok = 1; /* Now acting as a sign flag. */ } else { - auv = (aiv == IV_MIN) ? (UV)aiv : (UV)(-aiv); + auv = -(UV)aiv; } } a_valid = 1; @@ -1541,7 +1541,7 @@ PP(pp_add) buv = biv; buvok = 1; } else - buv = (biv == IV_MIN) ? (UV)biv : (UV)(-biv); + buv = -(UV)biv; } /* ?uvok if value is >= 0. basically, flagged as UV if it's +ve, else "IV" now, independent of how it came in. diff --git a/sv.c b/sv.c index 983646f335..b10f205033 100644 --- a/sv.c +++ b/sv.c @@ -2868,7 +2868,7 @@ S_uiv_2buf(char *const buf, const IV iv, UV uv, const int is_uv, char **const pe uv = iv; sign = 0; } else { - uv = (iv == IV_MIN) ? (UV)iv : (UV)(-iv); + uv = -(UV)iv; sign = 1; } do { @@ -12596,7 +12596,7 @@ Perl_sv_vcatpvfn_flags(pTHX_ SV *const sv, const char *const pat, const STRLEN p esignbuf[esignlen++] = plus; } else { - uv = (iv == IV_MIN) ? (UV)iv : (UV)(-iv); + uv = -(UV)iv; esignbuf[esignlen++] = '-'; } } -- Perl5 Master Repository