[Python-checkins] bpo-38858: Allocate small integers on the heap (GH-17301)

Victor Stinner webhook-mailer at python.org
Thu Nov 21 02:52:03 EST 2019


https://github.com/python/cpython/commit/5dcc06f6e0d7b5d6589085692b86c63e35e2325e
commit: 5dcc06f6e0d7b5d6589085692b86c63e35e2325e
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2019-11-21T08:51:59+01:00
summary:

bpo-38858: Allocate small integers on the heap (GH-17301)

Allocate small Python integers (small_ints of longobject.c) on the
heap, rather than using static objects.

files:
M Objects/longobject.c

diff --git a/Objects/longobject.c b/Objects/longobject.c
index 2b57ea18666ee..294308e3e126d 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -40,7 +40,7 @@ PyObject *_PyLong_One = NULL;
    The integers that are preallocated are those in the range
    -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
 */
-static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
+static PyLongObject* small_ints[NSMALLNEGINTS + NSMALLPOSINTS] = {0};
 
 #define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
 #define IS_SMALL_UINT(ival) ((ival) < NSMALLPOSINTS)
@@ -52,9 +52,8 @@ Py_ssize_t _Py_quick_int_allocs, _Py_quick_neg_int_allocs;
 static PyObject *
 get_small_int(sdigit ival)
 {
-    PyObject *v;
     assert(IS_SMALL_INT(ival));
-    v = (PyObject *)&small_ints[ival + NSMALLNEGINTS];
+    PyObject *v = (PyObject*)small_ints[ival + NSMALLNEGINTS];
     Py_INCREF(v);
 #ifdef COUNT_ALLOCS
     if (ival >= 0)
@@ -5784,40 +5783,30 @@ int
 _PyLong_Init(void)
 {
 #if NSMALLNEGINTS + NSMALLPOSINTS > 0
-    int ival, size;
-    PyLongObject *v = small_ints;
-
-    for (ival = -NSMALLNEGINTS; ival <  NSMALLPOSINTS; ival++, v++) {
-        size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
-        if (Py_TYPE(v) == &PyLong_Type) {
-            /* The element is already initialized, most likely
-             * the Python interpreter was initialized before.
-             */
-            Py_ssize_t refcnt;
-            PyObject* op = (PyObject*)v;
-
-            refcnt = Py_REFCNT(op) < 0 ? 0 : Py_REFCNT(op);
-            _Py_NewReference(op);
-            /* _Py_NewReference sets the ref count to 1 but
-             * the ref count might be larger. Set the refcnt
-             * to the original refcnt + 1 */
-            Py_REFCNT(op) = refcnt + 1;
-            assert(Py_SIZE(op) == size);
-            assert(v->ob_digit[0] == (digit)abs(ival));
-        }
-        else {
-            (void)PyObject_INIT(v, &PyLong_Type);
+    for (Py_ssize_t i=0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
+        sdigit ival = (sdigit)i - NSMALLNEGINTS;
+        int size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
+
+        PyLongObject *v = _PyLong_New(1);
+        if (!v) {
+            return -1;
         }
+
         Py_SIZE(v) = size;
         v->ob_digit[0] = (digit)abs(ival);
+
+        small_ints[i] = v;
     }
 #endif
     _PyLong_Zero = PyLong_FromLong(0);
-    if (_PyLong_Zero == NULL)
+    if (_PyLong_Zero == NULL) {
         return 0;
+    }
+
     _PyLong_One = PyLong_FromLong(1);
-    if (_PyLong_One == NULL)
+    if (_PyLong_One == NULL) {
         return 0;
+    }
 
     /* initialize int_info */
     if (Int_InfoType.tp_name == NULL) {
@@ -5832,17 +5821,11 @@ _PyLong_Init(void)
 void
 _PyLong_Fini(void)
 {
-    /* Integers are currently statically allocated. Py_DECREF is not
-       needed, but Python must forget about the reference or multiple
-       reinitializations will fail. */
     Py_CLEAR(_PyLong_One);
     Py_CLEAR(_PyLong_Zero);
 #if NSMALLNEGINTS + NSMALLPOSINTS > 0
-    int i;
-    PyLongObject *v = small_ints;
-    for (i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++, v++) {
-        _Py_DEC_REFTOTAL;
-        _Py_ForgetReference((PyObject*)v);
+    for (Py_ssize_t i = 0; i < NSMALLNEGINTS + NSMALLPOSINTS; i++) {
+        Py_CLEAR(small_ints[i]);
     }
 #endif
 }



More information about the Python-checkins mailing list