diff -r f24a82f00a96 Modules/_json.c --- a/Modules/_json.c Wed Aug 15 10:51:42 2012 +0200 +++ b/Modules/_json.c Wed Aug 15 10:56:45 2012 +0200 @@ -22,13 +22,48 @@ #define UNUSED #endif -#define PyScanner_Check(op) PyObject_TypeCheck(op, &PyScannerType) -#define PyScanner_CheckExact(op) (Py_TYPE(op) == &PyScannerType) -#define PyEncoder_Check(op) PyObject_TypeCheck(op, &PyEncoderType) -#define PyEncoder_CheckExact(op) (Py_TYPE(op) == &PyEncoderType) +typedef struct { + PyObject *PyScannerType; + PyObject *PyEncoderType; +} _jsonstate; -static PyTypeObject PyScannerType; -static PyTypeObject PyEncoderType; +#define _json_state(o) ((_jsonstate *) PyModule_GetState(o)) + +static int +_json_clear(PyObject *m) +{ + Py_CLEAR(_json_state(m)->PyScannerType); + Py_CLEAR(_json_state(m)->PyEncoderType); + return 0; +} + +static int +_json_traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(_json_state(m)->PyScannerType); + Py_VISIT(_json_state(m)->PyEncoderType); + return 0; +} + +static void +_json_free(void *m) +{ + _json_clear((PyObject *)m); +} + +static struct PyModuleDef jsonmodule; + +#define _jsonstate_global ((_jsonstate *) \ + PyModule_GetState(PyState_FindModule(&jsonmodule))) + +#define PyScanner_Check(op) PyObject_TypeCheck(op,\ + (PyTypeObject *)_jsonstate_global->PyScannerType) +#define PyScanner_CheckExact(op) \ + (Py_TYPE(op) == (PyTypeObject *)_jsonstate_global->PyScannerType) +#define PyEncoder_Check(op) \ + PyObject_TypeCheck(op, (PyTypeObject *)_jsonstate_global->PyEncoderType) +#define PyEncoder_CheckExact(op) \ + (Py_TYPE(op) == (PyTypeObject *)_jsonstate_global->PyEncoderType) typedef struct _PyScannerObject { PyObject_HEAD @@ -568,8 +603,12 @@ scanner_dealloc(PyObject *self) { /* Deallocate scanner object */ + PyTypeObject *type = Py_TYPE(self); scanner_clear(self); - Py_TYPE(self)->tp_free(self); + type->tp_free(self); + if((void *)type->tp_dealloc == (void *)scanner_dealloc) { + Py_DECREF(type); + } } static int @@ -1176,49 +1215,27 @@ PyDoc_STRVAR(scanner_doc, "JSON scanner object"); -static -PyTypeObject PyScannerType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_json.Scanner", /* tp_name */ - sizeof(PyScannerObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - scanner_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - scanner_call, /* tp_call */ - 0, /* tp_str */ - 0,/* PyObject_GenericGetAttr, */ /* tp_getattro */ - 0,/* PyObject_GenericSetAttr, */ /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - scanner_doc, /* tp_doc */ - scanner_traverse, /* tp_traverse */ - scanner_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - scanner_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - scanner_init, /* tp_init */ - 0,/* PyType_GenericAlloc, */ /* tp_alloc */ - scanner_new, /* tp_new */ - 0,/* PyObject_GC_Del, */ /* tp_free */ +static PyType_Slot PyScannerType_slots[] = { + {Py_tp_dealloc, scanner_dealloc}, + {Py_tp_call, scanner_call}, + {Py_tp_doc, scanner_doc}, + {Py_tp_traverse, scanner_traverse}, + {Py_tp_clear, scanner_clear}, + {Py_tp_members, scanner_members}, + {Py_tp_init, scanner_init}, + {Py_tp_new, scanner_new}, + {0, 0} }; +static PyType_Spec PyScannerType_spec = { + "_json.Scanner", + sizeof(PyScannerObject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + PyScannerType_slots, +}; + + static PyObject * encoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -1745,8 +1762,12 @@ encoder_dealloc(PyObject *self) { /* Deallocate Encoder */ + PyTypeObject *type = Py_TYPE(self); encoder_clear(self); - Py_TYPE(self)->tp_free(self); + type->tp_free(self); + if((void *)type->tp_dealloc == (void *)encoder_dealloc) { + Py_DECREF(type); + } } static int @@ -1786,49 +1807,27 @@ PyDoc_STRVAR(encoder_doc, "_iterencode(obj, _current_indent_level) -> iterable"); -static -PyTypeObject PyEncoderType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_json.Encoder", /* tp_name */ - sizeof(PyEncoderObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - encoder_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - encoder_call, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - encoder_doc, /* tp_doc */ - encoder_traverse, /* tp_traverse */ - encoder_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - encoder_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - encoder_init, /* tp_init */ - 0, /* tp_alloc */ - encoder_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot PyEncoderType_slots[] = { + {Py_tp_dealloc, encoder_dealloc}, + {Py_tp_call, encoder_call}, + {Py_tp_doc, encoder_doc}, + {Py_tp_traverse, encoder_traverse}, + {Py_tp_clear, encoder_clear}, + {Py_tp_members, encoder_members}, + {Py_tp_init, encoder_init}, + {Py_tp_new, encoder_new}, + {0, 0} }; +static PyType_Spec PyEncoderType_spec = { + "_json.Encoder", + sizeof(PyEncoderObject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + PyEncoderType_slots, +}; + + static PyMethodDef speedups_methods[] = { {"encode_basestring_ascii", (PyCFunction)py_encode_basestring_ascii, @@ -1848,34 +1847,39 @@ PyModuleDef_HEAD_INIT, "_json", module_doc, - -1, + sizeof(_jsonstate), speedups_methods, NULL, - NULL, - NULL, - NULL + _json_traverse, + _json_clear, + _json_free }; PyObject* PyInit__json(void) { - PyObject *m = PyModule_Create(&jsonmodule); + PyObject *m; + + m = PyModule_Create(&jsonmodule); if (!m) return NULL; - PyScannerType.tp_new = PyType_GenericNew; - if (PyType_Ready(&PyScannerType) < 0) + + _json_state(m)->PyScannerType = PyType_FromSpec(&PyScannerType_spec); + if (_json_state(m)->PyScannerType == NULL) goto fail; - PyEncoderType.tp_new = PyType_GenericNew; - if (PyType_Ready(&PyEncoderType) < 0) + + _json_state(m)->PyEncoderType = PyType_FromSpec(&PyEncoderType_spec); + if (_json_state(m)->PyEncoderType == NULL) goto fail; - Py_INCREF((PyObject*)&PyScannerType); - if (PyModule_AddObject(m, "make_scanner", (PyObject*)&PyScannerType) < 0) { - Py_DECREF((PyObject*)&PyScannerType); + + Py_INCREF(_json_state(m)->PyScannerType); + if (PyModule_AddObject(m, "make_scanner", _json_state(m)->PyScannerType) < 0) { + Py_DECREF(_json_state(m)->PyScannerType); goto fail; } - Py_INCREF((PyObject*)&PyEncoderType); - if (PyModule_AddObject(m, "make_encoder", (PyObject*)&PyEncoderType) < 0) { - Py_DECREF((PyObject*)&PyEncoderType); + Py_INCREF(_json_state(m)->PyEncoderType); + if (PyModule_AddObject(m, "make_encoder", _json_state(m)->PyEncoderType) < 0) { + Py_DECREF(_json_state(m)->PyEncoderType); goto fail; } return m;