Python 为了实现 GC,在 Object 头部增加了两个额外的指针,Python 作为一种高级语言,对 “Object” 有着强烈的执念,同时也造成内存效率较低,现在在新增了两个指针,真可谓是 “儿到荒年饭量增,屋漏偏逢连夜雨”。Python 3.8 中为了降低这一影响,对这两个指针的使用细致到了按位复用的程度。对于 gc_prev 指针:
// Include/cpython/objimpl.h:68
// 0 位表示已经执行过 tp_finalize
#define _PyGC_PREV_MASK_FINALIZED (1)
// 1 位表示对象正在被 GC
#define _PyGC_PREV_MASK_COLLECTING (2)
// 简单的 16 位操作系统, _PyGC_PREV_MASK 的值是 0b1111 1111 1111 1100
#define _PyGC_PREV_SHIFT (2)
#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
同样的,对于 gc_next 有:
// Modules/gcmodule.c:64
// 0 位表示 unreachable
#define NEXT_MASK_UNREACHABLE (1)
这两个指针看起来像这样:
gc_next 只是将闲置的最低 1 位利用起来,而 gc_prev 则在回收阶段被直接用作 gc_refs 有效引用记数,一直到 collect 函数中才被重建为指针。