Python-checkins
Threads by month
- ----- 2024 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
July 2021
- 1 participants
- 501 discussions
https://github.com/python/cpython/commit/818628c2da99ba0376313971816d472c65…
commit: 818628c2da99ba0376313971816d472c65c9a9fc
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2021-07-01T02:30:46+02:00
summary:
bpo-44531: Add _PyType_AllocNoTrack() function (GH-26947)
Add an internal _PyType_AllocNoTrack() function to allocate an object
without tracking it in the GC.
Modify dict_new() to use _PyType_AllocNoTrack(): dict subclasses are
now only tracked once all PyDictObject members are initialized.
Calling _PyObject_GC_UNTRACK() is no longer needed for the dict type.
Similar change in tuple_subtype_new() for tuple subclasses.
Replace tuple_gc_track() with _PyObject_GC_TRACK().
files:
M Include/internal/pycore_object.h
M Objects/dictobject.c
M Objects/tupleobject.c
M Objects/typeobject.c
diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 9dfc8c62babad..4091f5178eed1 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -178,6 +178,8 @@ extern int _Py_CheckSlotResult(
// See also the Py_TPFLAGS_READY flag.
#define _PyType_IsReady(type) ((type)->tp_dict != NULL)
+extern PyObject* _PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems);
+
#ifdef __cplusplus
}
#endif
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 3a1dbc994b44b..7f1d38dd5f43f 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -3324,19 +3324,16 @@ static PyNumberMethods dict_as_number = {
static PyObject *
dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- PyObject *self;
- PyDictObject *d;
+ assert(type != NULL);
+ assert(type->tp_alloc != NULL);
+ // dict subclasses must implement the GC protocol
+ assert(_PyType_IS_GC(type));
- assert(type != NULL && type->tp_alloc != NULL);
- self = type->tp_alloc(type, 0);
- if (self == NULL)
+ PyObject *self = type->tp_alloc(type, 0);
+ if (self == NULL) {
return NULL;
- d = (PyDictObject *)self;
-
- /* The object has been implicitly tracked by tp_alloc */
- if (type == &PyDict_Type) {
- _PyObject_GC_UNTRACK(d);
}
+ PyDictObject *d = (PyDictObject *)self;
d->ma_used = 0;
d->ma_version_tag = DICT_NEXT_VERSION();
@@ -3344,6 +3341,17 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
d->ma_keys = Py_EMPTY_KEYS;
d->ma_values = empty_values;
ASSERT_CONSISTENT(d);
+
+ if (type != &PyDict_Type) {
+ // Don't track if a subclass tp_alloc is PyType_GenericAlloc()
+ if (!_PyObject_GC_IS_TRACKED(d)) {
+ _PyObject_GC_TRACK(d);
+ }
+ }
+ else {
+ // _PyType_AllocNoTrack() does not track the created object
+ assert(!_PyObject_GC_IS_TRACKED(d));
+ }
return self;
}
@@ -3441,7 +3449,7 @@ PyTypeObject PyDict_Type = {
0, /* tp_descr_set */
0, /* tp_dictoffset */
dict_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
+ _PyType_AllocNoTrack, /* tp_alloc */
dict_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
.tp_vectorcall = dict_vectorcall,
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 6b1ab740121e8..b7fd421196dda 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -25,13 +25,6 @@ get_tuple_state(void)
#endif
-static inline void
-tuple_gc_track(PyTupleObject *op)
-{
- _PyObject_GC_TRACK(op);
-}
-
-
/* Print summary info about the state of the optimized allocator */
void
_PyTuple_DebugMallocStats(FILE *out)
@@ -48,10 +41,12 @@ _PyTuple_DebugMallocStats(FILE *out)
#endif
}
-/* Allocate an uninitialized tuple object. Before making it public following
+/* Allocate an uninitialized tuple object. Before making it public, following
steps must be done:
- - initialize its items
- - call tuple_gc_track() on it
+
+ - Initialize its items.
+ - Call _PyObject_GC_TRACK() on it.
+
Because the empty tuple is always reused and it's already tracked by GC,
this function must not be called with size == 0 (unless from PyTuple_New()
which wraps this function).
@@ -161,7 +156,7 @@ PyTuple_New(Py_ssize_t size)
for (Py_ssize_t i = 0; i < size; i++) {
op->ob_item[i] = NULL;
}
- tuple_gc_track(op);
+ _PyObject_GC_TRACK(op);
return (PyObject *) op;
}
@@ -257,7 +252,7 @@ PyTuple_Pack(Py_ssize_t n, ...)
items[i] = o;
}
va_end(vargs);
- tuple_gc_track(result);
+ _PyObject_GC_TRACK(result);
return (PyObject *)result;
}
@@ -473,7 +468,7 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
Py_INCREF(item);
dst[i] = item;
}
- tuple_gc_track(tuple);
+ _PyObject_GC_TRACK(tuple);
return (PyObject *)tuple;
}
@@ -551,7 +546,7 @@ tupleconcat(PyTupleObject *a, PyObject *bb)
Py_INCREF(v);
dest[i] = v;
}
- tuple_gc_track(np);
+ _PyObject_GC_TRACK(np);
return (PyObject *)np;
}
@@ -588,7 +583,7 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
p++;
}
}
- tuple_gc_track(np);
+ _PyObject_GC_TRACK(np);
return (PyObject *) np;
}
@@ -783,6 +778,9 @@ tuple_subtype_new(PyTypeObject *type, PyObject *iterable)
Py_ssize_t i, n;
assert(PyType_IsSubtype(type, &PyTuple_Type));
+ // tuple subclasses must implement the GC protocol
+ assert(_PyType_IS_GC(type));
+
tmp = tuple_new_impl(&PyTuple_Type, iterable);
if (tmp == NULL)
return NULL;
@@ -798,6 +796,11 @@ tuple_subtype_new(PyTypeObject *type, PyObject *iterable)
PyTuple_SET_ITEM(newobj, i, item);
}
Py_DECREF(tmp);
+
+ // Don't track if a subclass tp_alloc is PyType_GenericAlloc()
+ if (!_PyObject_GC_IS_TRACKED(newobj)) {
+ _PyObject_GC_TRACK(newobj);
+ }
return newobj;
}
@@ -857,7 +860,7 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
dest[i] = it;
}
- tuple_gc_track(result);
+ _PyObject_GC_TRACK(result);
return (PyObject *)result;
}
}
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 8ee4e813ee521..116ac14cbc2a6 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1164,7 +1164,7 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
PyObject *
-PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
+_PyType_AllocNoTrack(PyTypeObject *type, Py_ssize_t nitems)
{
PyObject *obj;
const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
@@ -1189,6 +1189,16 @@ PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
else {
_PyObject_InitVar((PyVarObject *)obj, type, nitems);
}
+ return obj;
+}
+
+PyObject *
+PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
+{
+ PyObject *obj = _PyType_AllocNoTrack(type, nitems);
+ if (obj == NULL) {
+ return NULL;
+ }
if (_PyType_IS_GC(type)) {
_PyObject_GC_TRACK(obj);
1
0