EVE Light on Life

Python源码学习(1) 整数

基本宏定义

#define PyObject_HEAD \      //定长对象固定头部内容
int ob_refcnt         \      //引用计数 
struct _typeobject *ob_type  //指向类型对象

#define PyObject_VAR_HEAD \  //变长对象固定头部内容
PyObject_HEAD \
int ob_size                  //变长对象一共容纳了多少个元素

#define _Py_Dealloc(op)	((*(op)->ob_type->tp_dealloc)((PyObject *)(op)))
#define Py_INCREF(op) ((op)->ob_refcnt++)  //增加对象引用计数
#define Py_DECREF(op) \                    //减少对象引用计数
if (--(op)->ob_refcnt != 0) \
	; \
else \
	_Py_Dealloc((PyObejct *)(op))

对象定义

typedef struct {
	PyObject_HEAD  
} PyObject;      //定长对象

typedef struct {
	PyObject_VAR_HEAD  
	int ob_size;
} PyVarObject;   //变长对象

整数对象

定义

typedef struct {
	PyObject_HEAD  
	long ob_ival;
} PyIntObject;

//另:
//在PyIntBlock里
//PyObject_HEAD头里的ob_type指针用于链表的next连接

创建对象

通过 PyObject *PyInt_FromLong(long ival) 创建

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;
}


小整数缓存池

#define NSAMLLNEGINTS 5
#define NSMALLPOSINTS 257

static PyIntObject *small_ints[NSAMLLNEGINTS + NSMALLPOSINTS];

小整数范围是[-NSAMLLNEGINTS,NSMALLPOSINTS),即[-5,257)

通过_PyInt_Init(void)函数初始化,存在PyIntBlock结构链表中。

整数内存链表

维护一个PyIntBlock结构的链表

struct _intblock {
	struct _intblock *next;
	PyIntObject objetcs[N_INTOBJECTS];
}
typedef _intblock PyIntBlock;

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

//block_list为PyintBlock结构链表指针
//free_list为PyIntBlock里面PyIntObject数组的指针,所有PyIntBlock结构里的objetcs数组都会连接起来

当free_list变为NULL时就会调用fill_free_list函数。所有PyIntBlock空闲内存都没有时,free_list也就变成了NULL。

static PyIntObject *
fill_free_list(void)
{
    PyIntObject *p, *q;
    /* Python's object allocator isn't appropriate for large blocks. */
    p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));
    if (p == NULL)
        return (PyIntObject *) PyErr_NoMemory();
    ((PyIntBlock *)p)->next = block_list;
    block_list = (PyIntBlock *)p;
    /* Link the int objects together, from rear to front, then return
       the address of the last int object in the block. */
    p = &((PyIntBlock *)p)->objects[0];
    q = p + N_INTOBJECTS;
    while (--q > p)
        Py_TYPE(q) = (struct _typeobject *)(q-1);
    Py_TYPE(q) = NULL;
    return p + N_INTOBJECTS - 1;
}

通用整数

一旦通用整数对象内存被申请,即使对象引用计数变为0,仅是删除了该对象内容,但不释放该对象所占的空间,留在链表中供下一个新建通用整数使用。

对象销毁

整数对象的引用计数变为0时,将执行整数对象的tp_dealloc操作: 一个整数对象销毁时,它的内存并没有释放,留在PyIntBlock上,freelist指针重新指向这个刚销毁的对象空间。

static void int_dealloc(PyIntObject *v)
{
    if (PyInt_CheckExact(v)) {
        v->ob_type = (struct _typeobject *)freelist;
        freelist = v;
    }
    else
        v->ob_type->tp_free((PyObject *)v);
}