Skip to content

Commit 9a26db7

Browse files
methanepicnixz
authored andcommitted
pythongh-127417: fix UTF-8 decoder optimization on AIX (python#127433)
1 parent 50eda43 commit 9a26db7

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

Objects/unicodeobject.c

+14-10
Original file line numberDiff line numberDiff line change
@@ -5014,21 +5014,26 @@ ctz(size_t v)
50145014
#endif /* SIZEOF_SIZE_T */
50155015
return pos;
50165016
}
5017+
#else
5018+
#define HAVE_CTZ 0
50175019
#endif
50185020

5019-
#if HAVE_CTZ
5020-
// load p[0]..p[size-1] as a little-endian size_t
5021-
// without unaligned access nor read ahead.
5021+
#if HAVE_CTZ && PY_LITTLE_ENDIAN
5022+
// load p[0]..p[size-1] as a size_t without unaligned access nor read ahead.
50225023
static size_t
50235024
load_unaligned(const unsigned char *p, size_t size)
50245025
{
5025-
assert(size <= SIZEOF_SIZE_T);
50265026
union {
50275027
size_t s;
50285028
unsigned char b[SIZEOF_SIZE_T];
50295029
} u;
50305030
u.s = 0;
5031+
// This switch statement assumes little endian because:
5032+
// * union is faster than bitwise or and shift.
5033+
// * big endian machine is rare and hard to maintain.
50315034
switch (size) {
5035+
default:
5036+
#if SIZEOF_SIZE_T == 8
50325037
case 8:
50335038
u.b[7] = p[7];
50345039
_Py_FALLTHROUGH;
@@ -5041,6 +5046,7 @@ load_unaligned(const unsigned char *p, size_t size)
50415046
case 5:
50425047
u.b[4] = p[4];
50435048
_Py_FALLTHROUGH;
5049+
#endif
50445050
case 4:
50455051
u.b[3] = p[3];
50465052
_Py_FALLTHROUGH;
@@ -5055,8 +5061,6 @@ load_unaligned(const unsigned char *p, size_t size)
50555061
break;
50565062
case 0:
50575063
break;
5058-
default:
5059-
Py_UNREACHABLE();
50605064
}
50615065
return u.s;
50625066
}
@@ -5077,20 +5081,20 @@ find_first_nonascii(const unsigned char *start, const unsigned char *end)
50775081

50785082
if (end - start >= SIZEOF_SIZE_T) {
50795083
const unsigned char *p2 = _Py_ALIGN_UP(p, SIZEOF_SIZE_T);
5084+
#if PY_LITTLE_ENDIAN && HAVE_CTZ
50805085
if (p < p2) {
5081-
#if HAVE_CTZ
50825086
#if defined(_M_AMD64) || defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)
50835087
// x86 and amd64 are little endian and can load unaligned memory.
50845088
size_t u = *(const size_t*)p & ASCII_CHAR_MASK;
50855089
#else
50865090
size_t u = load_unaligned(p, p2 - p) & ASCII_CHAR_MASK;
50875091
#endif
50885092
if (u) {
5089-
return p - start + (ctz(u) - 7) / 8;
5093+
return (ctz(u) - 7) / 8;
50905094
}
50915095
p = p2;
50925096
}
5093-
#else
5097+
#else /* PY_LITTLE_ENDIAN && HAVE_CTZ */
50945098
while (p < p2) {
50955099
if (*p & 0x80) {
50965100
return p - start;
@@ -5113,7 +5117,7 @@ find_first_nonascii(const unsigned char *start, const unsigned char *end)
51135117
p += SIZEOF_SIZE_T;
51145118
}
51155119
}
5116-
#if HAVE_CTZ
5120+
#if PY_LITTLE_ENDIAN && HAVE_CTZ
51175121
// we can not use *(const size_t*)p to avoid buffer overrun.
51185122
size_t u = load_unaligned(p, end - p) & ASCII_CHAR_MASK;
51195123
if (u) {

0 commit comments

Comments
 (0)