]> granicus.if.org Git - python/commitdiff
bpo-30248: Convert boolean arguments only once in _json. (#1423)
authorSerhiy Storchaka <storchaka@gmail.com>
Sun, 28 May 2017 12:31:49 +0000 (15:31 +0300)
committerGitHub <noreply@github.com>
Sun, 28 May 2017 12:31:49 +0000 (15:31 +0300)
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.

Modules/_json.c

index e78e3711121c2baeec0fad34800be78cb75ef697..f574004b38e002a7029251eb54e44caa63892b95 100644 (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;
 }