Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote headers #16

Open
wants to merge 12 commits into
base: gilectomy
Choose a base branch
from
2 changes: 1 addition & 1 deletion Doc/c-api/structures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ the definition of all other Python objects.

This macro is used to access the :attr:`ob_refcnt` member of a Python
object.
It expands to::
It might expand to::

(((PyObject*)(o))->ob_refcnt)

Expand Down
57 changes: 38 additions & 19 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ whose size is determined when the object is allocated.

#define PyObject_HEAD_INIT(type) \
{ _PyObject_EXTRA_INIT \
1, type },
0, type },

#define PyVarObject_HEAD_INIT(type, size) \
{ PyObject_HEAD_INIT(type) size },
Expand All @@ -134,7 +134,7 @@ whose size is determined when the object is allocated.
*/
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
Py_ssize_t *ob_refcnt_ptr;
struct _typeobject *ob_type;
} PyObject;

Expand All @@ -143,7 +143,17 @@ typedef struct {
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;

#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
/* API Functions for allocating the refcount. */
void _PyRefcount_New(PyObject *);
void _PyRefcount_Del(PyObject *);

/* Read-only access to the refcount (for most uses). */
#define Py_REFCNT(ob) ((const Py_ssize_t)*(((PyObject*)(ob))->ob_refcnt_ptr))
/* Read-write access to the refcount (without checking pointer validity). */
#define _Py_REFCNT(ob) (*((PyObject*)(ob))->ob_refcnt_ptr)
/* Assignment to refcount, without checking pointer validity. */
#define Py_SET_REFCNT(ob, val) (_Py_REFCNT(ob) = (val))

#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)

Expand Down Expand Up @@ -737,17 +747,18 @@ you can count such references to the type object.)
* e.g, defining _Py_NewReference five different times in a maze of nested
* #ifdefs (we used to do that -- it was impenetrable).
*/
PyAPI_FUNC(PyObject *) _PyDict_Dummy(void);

#ifdef Py_REF_DEBUG
PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
PyAPI_FUNC(void) _Py_NegativeRefcount(const char *fname,
int lineno, PyObject *op);
PyAPI_FUNC(PyObject *) _PyDict_Dummy(void);
PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void);
#define _Py_INC_REFTOTAL _Py_RefTotal++
#define _Py_DEC_REFTOTAL _Py_RefTotal--
#define _Py_REF_DEBUG_COMMA ,
#define _Py_CHECK_REFCNT(OP) \
{ if (((PyObject*)OP)->ob_refcnt < 0) \
{ if (Py_REFCNT((PyObject*)OP) < 0) \
_Py_NegativeRefcount(__FILE__, __LINE__, \
(PyObject *)(OP)); \
}
Expand Down Expand Up @@ -794,9 +805,11 @@ PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force);
#define _Py_NewReference(op) ( \
_Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA \
_Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \
Py_REFCNT(op) = 1)
_PyRefcount_New(op))

#define _Py_ForgetReference(op) _Py_INC_TPFREES(op)
#define _Py_ForgetReference(op) ( \
_Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA \
_PyRefcount_Del(op))

#ifdef Py_LIMITED_API
PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
Expand All @@ -807,14 +820,20 @@ PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
#endif
#endif /* !Py_TRACE_REFS */

/* For PyModuleDefs and other objects that are statically initialized,
* allocate the refcount iff it isn't already allocated. Can't do this in
* the general case as the object may consist of uninitialized memory. */
#define _Py_MaybeNewReference(op) ( \
((PyObject *)(op))->ob_refcnt_ptr == NULL ? _Py_NewReference(op) : 0)

#ifdef PY_TIME_REFCOUNTS

Py_LOCAL_INLINE(int) __py_incref__(PyObject *o) {
uint64_t start, delta;
py_time_refcounts_t *t = PyState_GetThisThreadPyTimeRefcounts();
_Py_INC_REFTOTAL;
start = fast_get_cycles();
ATOMIC_INC(&o->ob_refcnt);
ATOMIC_INC(&_Py_REFCNT(o));
delta = fast_get_cycles() - start;
PY_TIME_FETCH_AND_ADD(t, total_refcount_time, delta);
PY_TIME_FETCH_AND_ADD(t, total_refcounts, 1);
Expand All @@ -826,7 +845,7 @@ Py_LOCAL_INLINE(void) __py_decref__(PyObject *o) {
py_time_refcounts_t *t = PyState_GetThisThreadPyTimeRefcounts();
_Py_DEC_REFTOTAL;
start = fast_get_cycles();
new_rc = ATOMIC_DEC(&(o->ob_refcnt), 1);
new_rc = ATOMIC_DEC(&_Py_REFCNT(o), 1);
delta = fast_get_cycles() - start;
PY_TIME_FETCH_AND_ADD(t, total_refcount_time, delta);
PY_TIME_FETCH_AND_ADD(t, total_refcounts, 1);
Expand All @@ -846,16 +865,16 @@ Py_LOCAL_INLINE(void) __py_decref__(PyObject *o) {

#define Py_INCREF(op) ( \
_Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \
ATOMIC_INC(&(((PyObject *)(op))->ob_refcnt)) )

#define Py_DECREF(op) \
do { \
PyObject *_py_decref_tmp = (PyObject *)(op); \
if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \
ATOMIC_DEC(&(_py_decref_tmp->ob_refcnt)) != 0) \
_Py_CHECK_REFCNT(_py_decref_tmp) \
else \
_Py_Dealloc(_py_decref_tmp); \
ATOMIC_INC(&_Py_REFCNT(op)))

#define Py_DECREF(op) \
do { \
PyObject *_py_decref_tmp = (PyObject *)(op); \
if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \
ATOMIC_DEC(&_Py_REFCNT(_py_decref_tmp)) != 0) \
_Py_CHECK_REFCNT(_py_decref_tmp) \
else \
_Py_Dealloc(_py_decref_tmp); \
} while (0)

#endif /* PY_TIME_REFCOUNTS */
Expand Down
2 changes: 1 addition & 1 deletion Modules/_functoolsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ functools_reduce(PyObject *self, PyObject *args)
for (;;) {
PyObject *op2;

if (args->ob_refcnt > 1) {
if (Py_REFCNT(args) > 1) {
Py_DECREF(args);
if ((args = PyTuple_New(2)) == NULL)
goto Fail;
Expand Down
2 changes: 2 additions & 0 deletions Modules/_testbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2836,10 +2836,12 @@ PyInit__testbuffer(void)
return NULL;

Py_TYPE(&NDArray_Type) = &PyType_Type;
PyType_Ready(&NDArray_Type);
Py_INCREF(&NDArray_Type);
PyModule_AddObject(m, "ndarray", (PyObject *)&NDArray_Type);

Py_TYPE(&StaticArray_Type) = &PyType_Type;
PyType_Ready(&StaticArray_Type);
Py_INCREF(&StaticArray_Type);
PyModule_AddObject(m, "staticarray", (PyObject *)&StaticArray_Type);

Expand Down
13 changes: 7 additions & 6 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2710,8 +2710,8 @@ slot_tp_del(PyObject *self)
PyObject *error_type, *error_value, *error_traceback;

/* Temporarily resurrect the object. */
assert(self->ob_refcnt == 0);
self->ob_refcnt = 1;
assert(Py_REFCNT(self) == 0);
_Py_REFCNT(self) = 1;

/* Save the current exception, if any. */
PyErr_Fetch(&error_type, &error_value, &error_traceback);
Expand All @@ -2733,17 +2733,17 @@ slot_tp_del(PyObject *self)
/* Undo the temporary resurrection; can't use DECREF here, it would
* cause a recursive call.
*/
assert(self->ob_refcnt > 0);
if (--self->ob_refcnt == 0)
assert(Py_REFCNT(self) > 0);
if (--_Py_REFCNT(self) == 0)
return; /* this is the normal path out */

/* __del__ resurrected it! Make it look like the original Py_DECREF
* never happened.
*/
{
Py_ssize_t refcnt = self->ob_refcnt;
Py_ssize_t refcnt = Py_REFCNT(self);
_Py_NewReference(self);
self->ob_refcnt = refcnt;
_Py_REFCNT(self) = refcnt;
}
assert(!PyType_IS_GC(Py_TYPE(self)) ||
_Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
Expand Down Expand Up @@ -4088,6 +4088,7 @@ PyInit__testcapi(void)
Py_TYPE(&_HashInheritanceTester_Type)=&PyType_Type;

Py_TYPE(&test_structmembersType)=&PyType_Type;
PyType_Ready(&test_structmembersType);
Py_INCREF(&test_structmembersType);
/* don't use a name starting with "test", since we don't want
test_capi to automatically call this */
Expand Down
5 changes: 3 additions & 2 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -4146,7 +4146,7 @@ sock_dealloc(PySocketSockObject *s)
if (s->sock_fd != -1) {
PyObject *exc, *val, *tb;
Py_ssize_t old_refcount = Py_REFCNT(s);
++Py_REFCNT(s);
++_Py_REFCNT(s);
PyErr_Fetch(&exc, &val, &tb);
if (PyErr_WarnFormat(PyExc_ResourceWarning, 1,
"unclosed %R", s))
Expand All @@ -4155,7 +4155,7 @@ sock_dealloc(PySocketSockObject *s)
PyErr_WriteUnraisable((PyObject *) s);
PyErr_Restore(exc, val, tb);
(void) SOCKETCLOSE(s->sock_fd);
Py_REFCNT(s) = old_refcount;
_Py_REFCNT(s) = old_refcount;
}
Py_TYPE(s)->tp_free((PyObject *)s);
}
Expand Down Expand Up @@ -6088,6 +6088,7 @@ PyInit__socket(void)
#endif

Py_TYPE(&sock_type) = &PyType_Type;
PyType_Ready(&sock_type);
m = PyModule_Create(&socketmodule);
if (m == NULL)
return NULL;
Expand Down
1 change: 1 addition & 0 deletions Modules/unicodedata.c
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,7 @@ PyInit_unicodedata(void)
PyObject *m, *v;

Py_TYPE(&UCD_Type) = &PyType_Type;
PyType_Ready(&UCD_Type);

m = PyModule_Create(&unicodedatamodule);
if (!m)
Expand Down
6 changes: 2 additions & 4 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,11 @@ static PyObject _dummy_struct;

#define dummy (&_dummy_struct)

#ifdef Py_REF_DEBUG
PyObject *
_PyDict_Dummy(void)
{
return dummy;
}
#endif

/* forward declarations */
static PyDictKeyEntry *lookdict(PyDictObject *mp, PyObject *key,
Expand Down Expand Up @@ -3450,7 +3448,7 @@ static PyObject *dictiter_iternextitem(dictiterobject *di)
if (i > mask)
goto fail;

if (result->ob_refcnt == 1) {
if (Py_REFCNT(result) == 1) {
Py_INCREF(result);
Py_DECREF(PyTuple_GET_ITEM(result, 0));
Py_DECREF(PyTuple_GET_ITEM(result, 1));
Expand Down Expand Up @@ -4240,6 +4238,6 @@ static PyTypeObject PyDictDummy_Type = {

static PyObject _dummy_struct = {
_PyObject_EXTRA_INIT
2, &PyDictDummy_Type
NULL, &PyDictDummy_Type
};

4 changes: 2 additions & 2 deletions Objects/enumobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ enum_next_long(enumobject *en, PyObject* next_item)
return NULL;
en->en_longindex = stepped_up;

if (result->ob_refcnt == 1) {
if (Py_REFCNT(result) == 1) {
Py_INCREF(result);
Py_DECREF(PyTuple_GET_ITEM(result, 0));
Py_DECREF(PyTuple_GET_ITEM(result, 1));
Expand Down Expand Up @@ -141,7 +141,7 @@ enum_next(enumobject *en)
}
en->en_index++;

if (result->ob_refcnt == 1) {
if (Py_REFCNT(result) == 1) {
Py_INCREF(result);
Py_DECREF(PyTuple_GET_ITEM(result, 0));
Py_DECREF(PyTuple_GET_ITEM(result, 1));
Expand Down
2 changes: 1 addition & 1 deletion Objects/fileobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ PyFile_GetLine(PyObject *f, int n)
"EOF when reading a line");
}
else if (s[len-1] == '\n') {
if (result->ob_refcnt == 1)
if (Py_REFCNT(result) == 1)
_PyBytes_Resize(&result, len-1);
else {
PyObject *v;
Expand Down
2 changes: 1 addition & 1 deletion Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -5361,7 +5361,7 @@ _PyLong_Init(void)
/* _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;
Py_SET_REFCNT(op, refcnt + 1);
assert(Py_SIZE(op) == size);
assert(v->ob_digit[0] == (digit)abs(ival));
}
Expand Down
2 changes: 1 addition & 1 deletion Objects/moduleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ PyModuleDef_Init(struct PyModuleDef* def)
{
if (PyType_Ready(&PyModuleDef_Type) < 0)
return NULL;
_Py_MaybeNewReference(def);
if (def->m_base.m_index == 0) {
max_module_number++;
Py_REFCNT(def) = 1;
Py_TYPE(def) = &PyModuleDef_Type;
def->m_base.m_index = max_module_number;
}
Expand Down
Loading