Pythonにおける整数オブジェクトの実装


Pythonの整数オブジェクトの実装を理解することは、Pythonのオブジェクトシステムを理解するのに役立ちます.ここ数日の読書内容をメモします.
PyIntobjectは、PyObjec_からなる構造体です.HEADとint ob_ivalの構成は、次のとおりです.
typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

PyObject_HEADという構造体には、int refリファレンスカウンタ、struct_という2つのフィールドがあります.typeobject * ob_typeはタイプのポインタを表します.
Python整数タイプは小整数と大整数に分けられ、頻繁に使用される小整数については、参照カウント方式を採用し、同じ値で同じメモリを共有し、python初期化時に割り当てられます.
普通は-5~257で、自分で調整できます.この数に対して、完全にキャッシュされます.
#ifndef NSMALLPOSINTS
#define NSMALLPOSINTS           257
#endif
#ifndef NSMALLNEGINTS
#define NSMALLNEGINTS           5
#endif
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
#endif

大きな整数の場合、PyIntBlock構造を使用して単相リストを実現し、メモリをリンクし、使用するときはfree_リストから1枚取り出します.
#define BLOCK_SIZE      1000    /* 1K less typical malloc overhead */
#define BHEAD_SIZE      8       /* Enough for a 64-bit pointer */
#define N_INTOBJECTS    ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyIntObject))

struct _intblock {
    struct _intblock *next;
    PyIntObject objects[N_INTOBJECTS];
};

typedef struct _intblock PyIntBlock;

static PyIntBlock *block_list = NULL;
static PyIntObject *free_list = NULL;

もちろん、delが大きな整数オブジェクトの場合、メモリをシステムに返すのではなく、フリーチェーンテーブルに追加します.
最後に、整数オブジェクトの作成を見てみましょう.
PyObject *
PyInt_FromLong(long ival)
{
    register PyIntObject *v;
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
    if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
        v = small_ints[ival + NSMALLNEGINTS];
        Py_INCREF(v);
#ifdef COUNT_ALLOCS
        if (ival >= 0)
            quick_int_allocs++;
        else
            quick_neg_int_allocs++;
#endif
        return (PyObject *) v;
    }
#endif
    if (free_list == NULL) {
        if ((free_list = fill_free_list()) == NULL)
            return NULL;
    }
    /* Inline PyObject_New */
    v = free_list;
    free_list = (PyIntObject *)Py_TYPE(v);
    PyObject_INIT(v, &PyInt_Type);
    v->ob_ival = ival;
    return (PyObject *) v;
}