Skip to content
Prev Previous commit
Next Next commit
add _PyObject_IS_GC()
  • Loading branch information
shihai1991 committed Apr 13, 2020
commit 0783d0b42ab56d18197b1a1793b4cb3225259dae
12 changes: 11 additions & 1 deletion Include/cpython/objimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ PyAPI_FUNC(Py_ssize_t) _PyGC_CollectIfEnabled(void);
/* Test if an object has a GC head */
Comment thread
shihai1991 marked this conversation as resolved.
Outdated
PyAPI_FUNC(int) PyObject_IS_GC(PyObject *obj);

/* Fast inlined version of PyObject_IS_GC() */
static inline int
_PyObject_IS_GC(PyObject *obj)
Comment thread
shihai1991 marked this conversation as resolved.
Outdated
{
if (PyType_IS_GC(Py_TYPE(obj))) {
return (Py_TYPE(obj)->tp_is_gc == NULL || Py_TYPE(obj)->tp_is_gc(obj));
}
return 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (PyType_IS_GC(Py_TYPE(obj))) {
return (Py_TYPE(obj)->tp_is_gc == NULL || Py_TYPE(obj)->tp_is_gc(obj));
}
return 0;
return (PyType_IS_GC(Py_TYPE(obj))
&& (Py_TYPE(obj)->tp_is_gc == NULL
|| Py_TYPE(obj)->tp_is_gc(obj)));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code style looks more simple?

}

/* GC information is stored BEFORE the object structure. */
typedef struct {
// Pointer to next object in the list.
Expand All @@ -142,7 +152,7 @@ typedef struct {
/* True if the object may be tracked by the GC in the future, or already is.
This can be useful to implement some optimizations. */
#define _PyObject_GC_MAY_BE_TRACKED(obj) \
(PyObject_IS_GC(obj) && \
(_PyObject_IS_GC(obj) && \
(!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))


Expand Down
21 changes: 9 additions & 12 deletions Modules/gcmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ visit_decref(PyObject *op, void *parent)
{
_PyObject_ASSERT(_PyObject_CAST(parent), !_PyObject_IsFreed(op));

if (PyObject_IS_GC(op)) {
if (_PyObject_IS_GC(op)) {
PyGC_Head *gc = AS_GC(op);
/* We're only interested in gc_refs for objects in the
* generation being collected, which can be recognized
Expand Down Expand Up @@ -477,7 +477,7 @@ subtract_refs(PyGC_Head *containers)
static int
visit_reachable(PyObject *op, PyGC_Head *reachable)
{
if (!PyObject_IS_GC(op)) {
if (!_PyObject_IS_GC(op)) {
return 0;
}

Expand Down Expand Up @@ -704,7 +704,7 @@ clear_unreachable_mask(PyGC_Head *unreachable)
static int
visit_move(PyObject *op, PyGC_Head *tolist)
{
if (PyObject_IS_GC(op)) {
if (_PyObject_IS_GC(op)) {
PyGC_Head *gc = AS_GC(op);
if (gc_is_collecting(gc)) {
gc_list_move(gc, tolist);
Expand Down Expand Up @@ -1715,7 +1715,7 @@ gc_get_referents(PyObject *self, PyObject *args)
traverseproc traverse;
PyObject *obj = PyTuple_GET_ITEM(args, i);

if (! PyObject_IS_GC(obj))
if (!_PyObject_IS_GC(obj))
continue;
traverse = Py_TYPE(obj)->tp_traverse;
if (! traverse)
Expand Down Expand Up @@ -1855,7 +1855,7 @@ gc_is_tracked(PyObject *module, PyObject *obj)
{
PyObject *result;

if (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj))
if (_PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj))
result = Py_True;
else
result = Py_False;
Expand All @@ -1876,7 +1876,7 @@ static PyObject *
gc_is_finalized(PyObject *module, PyObject *obj)
/*[clinic end generated code: output=e1516ac119a918ed input=201d0c58f69ae390]*/
{
if (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(AS_GC(obj))) {
if (_PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(AS_GC(obj))) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
Expand Down Expand Up @@ -2207,10 +2207,7 @@ PyObject_GC_UnTrack(void *op_raw)
int
PyObject_IS_GC(PyObject *obj)
{
if (PyType_IS_GC(Py_TYPE(obj))) {
return (Py_TYPE(obj)->tp_is_gc == NULL || Py_TYPE(obj)->tp_is_gc(obj));
}
return 0;
return _PyObject_IS_GC(obj);
}

static PyObject *
Expand Down Expand Up @@ -2326,7 +2323,7 @@ PyObject_GC_Del(void *op)
int
PyObject_GC_IsTracked(PyObject* obj)
{
if (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)) {
if (_PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)) {
return 1;
}
return 0;
Expand All @@ -2335,7 +2332,7 @@ PyObject_GC_IsTracked(PyObject* obj)
int
PyObject_GC_IsFinalized(PyObject *obj)
{
if (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(AS_GC(obj))) {
if (_PyObject_IS_GC(obj) && _PyGCHead_FINALIZED(AS_GC(obj))) {
return 1;
}
return 0;
Expand Down
4 changes: 2 additions & 2 deletions Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -2030,7 +2030,7 @@ _PyTrash_deposit_object(PyObject *op)
PyThreadState *tstate = _PyThreadState_GET();
struct _gc_runtime_state *gcstate = &tstate->interp->gc;

_PyObject_ASSERT(op, PyObject_IS_GC(op));
_PyObject_ASSERT(op, _PyObject_IS_GC(op));
_PyObject_ASSERT(op, !_PyObject_GC_IS_TRACKED(op));
_PyObject_ASSERT(op, Py_REFCNT(op) == 0);
_PyGCHead_SET_PREV(_Py_AS_GC(op), gcstate->trash_delete_later);
Expand All @@ -2042,7 +2042,7 @@ void
_PyTrash_thread_deposit_object(PyObject *op)
{
PyThreadState *tstate = _PyThreadState_GET();
_PyObject_ASSERT(op, PyObject_IS_GC(op));
_PyObject_ASSERT(op, _PyObject_IS_GC(op));
_PyObject_ASSERT(op, !_PyObject_GC_IS_TRACKED(op));
_PyObject_ASSERT(op, Py_REFCNT(op) == 0);
_PyGCHead_SET_PREV(_Py_AS_GC(op), tstate->trash_delete_later);
Expand Down
2 changes: 1 addition & 1 deletion Python/sysmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,7 +1679,7 @@ _PySys_GetSizeOf(PyObject *o)
}

/* add gc_head size */
if (PyObject_IS_GC(o))
if (_PyObject_IS_GC(o))
return ((size_t)size) + sizeof(PyGC_Head);
return (size_t)size;
}
Expand Down