bpo-30248: Convert boolean arguments only once in _json. (#1423)

Rather than saving the Python object and calling PyObject_IsTrue()
every time when the boolean argument is used, call it only once and
save C boolean value.
This commit is contained in:
Serhiy Storchaka 2017-05-28 15:31:49 +03:00 committed by GitHub
parent 4a8bcdf79c
commit ac5bbd43bc
1 changed files with 24 additions and 40 deletions

View File

@ -18,7 +18,7 @@ static PyTypeObject PyEncoderType;
typedef struct _PyScannerObject {
PyObject_HEAD
PyObject *strict;
char strict;
PyObject *object_hook;
PyObject *object_pairs_hook;
PyObject *parse_float;
@ -28,7 +28,7 @@ typedef struct _PyScannerObject {
} PyScannerObject;
static PyMemberDef scanner_members[] = {
{"strict", T_OBJECT, offsetof(PyScannerObject, strict), READONLY, "strict"},
{"strict", T_BOOL, offsetof(PyScannerObject, strict), READONLY, "strict"},
{"object_hook", T_OBJECT, offsetof(PyScannerObject, object_hook), READONLY, "object_hook"},
{"object_pairs_hook", T_OBJECT, offsetof(PyScannerObject, object_pairs_hook), READONLY},
{"parse_float", T_OBJECT, offsetof(PyScannerObject, parse_float), READONLY, "parse_float"},
@ -45,10 +45,10 @@ typedef struct _PyEncoderObject {
PyObject *indent;
PyObject *key_separator;
PyObject *item_separator;
PyObject *sort_keys;
PyObject *skipkeys;
PyCFunction fast_encode;
char sort_keys;
char skipkeys;
int allow_nan;
PyCFunction fast_encode;
} PyEncoderObject;
static PyMemberDef encoder_members[] = {
@ -58,8 +58,8 @@ static PyMemberDef encoder_members[] = {
{"indent", T_OBJECT, offsetof(PyEncoderObject, indent), READONLY, "indent"},
{"key_separator", T_OBJECT, offsetof(PyEncoderObject, key_separator), READONLY, "key_separator"},
{"item_separator", T_OBJECT, offsetof(PyEncoderObject, item_separator), READONLY, "item_separator"},
{"sort_keys", T_OBJECT, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
{"skipkeys", T_OBJECT, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
{"sort_keys", T_BOOL, offsetof(PyEncoderObject, sort_keys), READONLY, "sort_keys"},
{"skipkeys", T_BOOL, offsetof(PyEncoderObject, skipkeys), READONLY, "skipkeys"},
{NULL}
};
@ -666,7 +666,6 @@ scanner_traverse(PyObject *self, visitproc visit, void *arg)
PyScannerObject *s;
assert(PyScanner_Check(self));
s = (PyScannerObject *)self;
Py_VISIT(s->strict);
Py_VISIT(s->object_hook);
Py_VISIT(s->object_pairs_hook);
Py_VISIT(s->parse_float);
@ -681,7 +680,6 @@ scanner_clear(PyObject *self)
PyScannerObject *s;
assert(PyScanner_Check(self));
s = (PyScannerObject *)self;
Py_CLEAR(s->strict);
Py_CLEAR(s->object_hook);
Py_CLEAR(s->object_pairs_hook);
Py_CLEAR(s->parse_float);
@ -692,7 +690,8 @@ scanner_clear(PyObject *self)
}
static PyObject *
_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr) {
_parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *next_idx_ptr)
{
/* Read a JSON object from PyUnicode pystr.
idx is the index of the first character after the opening curly brace.
*next_idx_ptr is a return-by-reference index to the first character after
@ -706,13 +705,9 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
PyObject *val = NULL;
PyObject *rval = NULL;
PyObject *key = NULL;
int strict = PyObject_IsTrue(s->strict);
int has_pairs_hook = (s->object_pairs_hook != Py_None);
Py_ssize_t next_idx;
if (strict < 0)
return NULL;
if (PyUnicode_READY(pystr) == -1)
return NULL;
@ -740,7 +735,7 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
raise_errmsg("Expecting property name enclosed in double quotes", pystr, idx);
goto bail;
}
key = scanstring_unicode(pystr, idx + 1, strict, &next_idx);
key = scanstring_unicode(pystr, idx + 1, s->strict, &next_idx);
if (key == NULL)
goto bail;
memokey = PyDict_GetItem(s->memo, key);
@ -1060,7 +1055,6 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
void *str;
int kind;
Py_ssize_t length;
int strict;
if (PyUnicode_READY(pystr) == -1)
return NULL;
@ -1081,10 +1075,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
switch (PyUnicode_READ(kind, str, idx)) {
case '"':
/* string */
strict = PyObject_IsTrue(s->strict);
if (strict < 0)
return NULL;
return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr);
return scanstring_unicode(pystr, idx + 1, s->strict, next_idx_ptr);
case '{':
/* object */
if (Py_EnterRecursiveCall(" while decoding a JSON object "
@ -1197,6 +1188,7 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyScannerObject *s;
PyObject *ctx;
PyObject *strict;
static char *kwlist[] = {"context", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:make_scanner", kwlist, &ctx))
@ -1212,8 +1204,12 @@ scanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
goto bail;
/* All of these will fail "gracefully" so we don't need to verify them */
s->strict = PyObject_GetAttrString(ctx, "strict");
if (s->strict == NULL)
strict = PyObject_GetAttrString(ctx, "strict");
if (strict == NULL)
goto bail;
s->strict = PyObject_IsTrue(strict);
Py_DECREF(strict);
if (s->strict < 0)
goto bail;
s->object_hook = PyObject_GetAttrString(ctx, "object_hook");
if (s->object_hook == NULL)
@ -1290,10 +1286,10 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyEncoderObject *s;
PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
PyObject *item_separator, *sort_keys, *skipkeys;
int allow_nan;
PyObject *item_separator;
int sort_keys, skipkeys, allow_nan;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUOOp:make_encoder", kwlist,
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOUUppp:make_encoder", kwlist,
&markers, &defaultfn, &encoder, &indent,
&key_separator, &item_separator,
&sort_keys, &skipkeys, &allow_nan))
@ -1318,6 +1314,7 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
s->item_separator = item_separator;
s->sort_keys = sort_keys;
s->skipkeys = skipkeys;
s->allow_nan = allow_nan;
s->fast_encode = NULL;
if (PyCFunction_Check(s->encoder)) {
PyCFunction f = PyCFunction_GetFunction(s->encoder);
@ -1326,7 +1323,6 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
s->fast_encode = f;
}
}
s->allow_nan = allow_nan;
Py_INCREF(s->markers);
Py_INCREF(s->defaultfn);
@ -1334,8 +1330,6 @@ encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_INCREF(s->indent);
Py_INCREF(s->key_separator);
Py_INCREF(s->item_separator);
Py_INCREF(s->sort_keys);
Py_INCREF(s->skipkeys);
return (PyObject *)s;
}
@ -1551,8 +1545,6 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
PyObject *it = NULL;
PyObject *items;
PyObject *item = NULL;
int skipkeys;
int sortkeys;
Py_ssize_t idx;
if (open_dict == NULL || close_dict == NULL || empty_dict == NULL) {
@ -1597,16 +1589,12 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
items = PyMapping_Items(dct);
if (items == NULL)
goto bail;
sortkeys = PyObject_IsTrue(s->sort_keys);
if (sortkeys < 0 || (sortkeys && PyList_Sort(items) < 0))
if (s->sort_keys && PyList_Sort(items) < 0)
goto bail;
it = PyObject_GetIter(items);
Py_DECREF(items);
if (it == NULL)
goto bail;
skipkeys = PyObject_IsTrue(s->skipkeys);
if (skipkeys < 0)
goto bail;
idx = 0;
while ((item = PyIter_Next(it)) != NULL) {
PyObject *encoded, *key, *value;
@ -1637,7 +1625,7 @@ encoder_listencode_dict(PyEncoderObject *s, _PyAccu *acc,
goto bail;
}
}
else if (skipkeys) {
else if (s->skipkeys) {
Py_DECREF(item);
continue;
}
@ -1805,8 +1793,6 @@ encoder_traverse(PyObject *self, visitproc visit, void *arg)
Py_VISIT(s->indent);
Py_VISIT(s->key_separator);
Py_VISIT(s->item_separator);
Py_VISIT(s->sort_keys);
Py_VISIT(s->skipkeys);
return 0;
}
@ -1823,8 +1809,6 @@ encoder_clear(PyObject *self)
Py_CLEAR(s->indent);
Py_CLEAR(s->key_separator);
Py_CLEAR(s->item_separator);
Py_CLEAR(s->sort_keys);
Py_CLEAR(s->skipkeys);
return 0;
}