Skip to content

Commit fa52a83

Browse files
committed
Mimimize the conditionals and the numer of ops inside the
json.loads hot path. This partially reverts the previous commit as we found out the culprit wasn't the MOV but the strictness checks
1 parent e78b873 commit fa52a83

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

Modules/_json.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -434,19 +434,20 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next
434434
while (1) {
435435
/* Find the end of the string or the next escape */
436436
Py_UCS4 c = 0;
437-
next = end;
438-
/* This is a tight loop in a hot path so we try to avoid
439-
MOV from the register variable into memory. See bpo-37587 */
440-
for (Py_UCS4 c_in = 0; next < len; next++) {
441-
c_in = PyUnicode_READ(kind, buf, next);
442-
if (c_in == '"' || c_in == '\\') {
443-
c = c_in;
437+
Py_ssize_t invalid = -1;
438+
for (next = end; next < len; next++) {
439+
c = PyUnicode_READ(kind, buf, next);
440+
if (c == '"' || c == '\\') {
444441
break;
445442
}
446-
else if (c_in <= 0x1f && strict) {
447-
raise_errmsg("Invalid control character at", pystr, next);
448-
goto bail;
449-
}
443+
/* Defer the strict error until outside this (hot) loop. */
444+
/* See bpo-37587 */
445+
if (c <= 0x1f && invalid < 0)
446+
invalid = next;
447+
}
448+
if (strict && invalid >= 0) {
449+
raise_errmsg("Invalid control character at", pystr, invalid);
450+
goto bail;
450451
}
451452
if (!(c == '"' || c == '\\')) {
452453
raise_errmsg("Unterminated string starting at", pystr, begin);

0 commit comments

Comments
 (0)