[Python-checkins] cpython: Close #18469: Replace PyDict_GetItemString() with _PyDict_GetItemId() in

victor.stinner python-checkins at python.org
Wed Jul 17 01:24:37 CEST 2013


http://hg.python.org/cpython/rev/af18829a7754
changeset:   84684:af18829a7754
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Wed Jul 17 01:22:45 2013 +0200
summary:
  Close #18469: Replace PyDict_GetItemString() with _PyDict_GetItemId() in structseq.c

_PyDict_GetItemId() is more efficient: it only builds the Unicode string once.
Identifiers (dictionary keys) are now created at Python initialization, and if
the creation failed, Python does exit with a fatal error.

Before, PyDict_GetItemString() failure was not handled: structseq_new() could
call PyObject_GC_NewVar() with a negative size, and structseq_dealloc() could
also crash.

files:
  Objects/structseq.c |  25 ++++++++++++++++++++-----
  Python/pythonrun.c  |   3 +++
  2 files changed, 23 insertions(+), 5 deletions(-)


diff --git a/Objects/structseq.c b/Objects/structseq.c
--- a/Objects/structseq.c
+++ b/Objects/structseq.c
@@ -11,17 +11,20 @@
 /* Fields with this name have only a field index, not a field name.
    They are only allowed for indices < n_visible_fields. */
 char *PyStructSequence_UnnamedField = "unnamed field";
+_Py_IDENTIFIER(n_sequence_fields);
+_Py_IDENTIFIER(n_fields);
+_Py_IDENTIFIER(n_unnamed_fields);
 
 #define VISIBLE_SIZE(op) Py_SIZE(op)
 #define VISIBLE_SIZE_TP(tp) PyLong_AsLong( \
-                      PyDict_GetItemString((tp)->tp_dict, visible_length_key))
+                      _PyDict_GetItemId((tp)->tp_dict, &PyId_n_sequence_fields))
 
 #define REAL_SIZE_TP(tp) PyLong_AsLong( \
-                      PyDict_GetItemString((tp)->tp_dict, real_length_key))
+                      _PyDict_GetItemId((tp)->tp_dict, &PyId_n_fields))
 #define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))
 
 #define UNNAMED_FIELDS_TP(tp) PyLong_AsLong( \
-                      PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key))
+                      _PyDict_GetItemId((tp)->tp_dict, &PyId_n_unnamed_fields))
 #define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))
 
 
@@ -59,7 +62,7 @@
 structseq_dealloc(PyStructSequence *obj)
 {
     Py_ssize_t i, size;
-    
+
     size = REAL_SIZE(obj);
     for (i = 0; i < size; ++i) {
         Py_XDECREF(obj->ob_item[i]);
@@ -382,9 +385,21 @@
 PyTypeObject*
 PyStructSequence_NewType(PyStructSequence_Desc *desc)
 {
-    PyTypeObject *result = (PyTypeObject*)PyType_GenericAlloc(&PyType_Type, 0);
+    PyTypeObject *result;
+
+    result = (PyTypeObject*)PyType_GenericAlloc(&PyType_Type, 0);
     if (result != NULL) {
         PyStructSequence_InitType(result, desc);
     }
     return result;
 }
+
+int _PyStructSequence_Init(void)
+{
+    if (_PyUnicode_FromId(&PyId_n_sequence_fields) == NULL
+        || _PyUnicode_FromId(&PyId_n_fields) == NULL
+        || _PyUnicode_FromId(&PyId_n_unnamed_fields) == NULL)
+        return -1;
+
+    return 0;
+}
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -86,6 +86,7 @@
 static void wait_for_thread_shutdown(void);
 static void call_ll_exitfuncs(void);
 extern int _PyUnicode_Init(void);
+extern int _PyStructSequence_Init(void);
 extern void _PyUnicode_Fini(void);
 extern int _PyLong_Init(void);
 extern void PyLong_Fini(void);
@@ -336,6 +337,8 @@
     /* Init Unicode implementation; relies on the codec registry */
     if (_PyUnicode_Init() < 0)
         Py_FatalError("Py_Initialize: can't initialize unicode");
+    if (_PyStructSequence_Init() < 0)
+        Py_FatalError("Py_Initialize: can't initialize structseq");
 
     bimod = _PyBuiltin_Init();
     if (bimod == NULL)

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list