Skip to content

Commit db532a0

Browse files
authored
bpo-39947: Remove old private trashcan C API functions (GH-26869)
Remove 4 C API private trashcan functions which were only kept for the backward compatibility of the stable ABI with Python 3.8 and older, since the trashcan API was not usable with the limited C API on Python 3.8 and older. The trashcan API was excluded from the limited C API in Python 3.9. Removed functions: * _PyTrash_deposit_object() * _PyTrash_destroy_chain() * _PyTrash_thread_deposit_object() * _PyTrash_thread_destroy_chain() The trashcan C API was never usable with the limited C API, since old trashcan macros accessed directly PyThreadState members like "_tstate->trash_delete_nesting", whereas the PyThreadState structure is opaque in the limited C API. Exclude also the PyTrash_UNWIND_LEVEL constant from the C API. The trashcan C API was modified in Python 3.9 by commit 38965ec and in Python 3.10 by commit ed1a5a5 to hide implementation details.
1 parent 2a396d6 commit db532a0

File tree

5 files changed

+30
-78
lines changed

5 files changed

+30
-78
lines changed

Include/cpython/object.h

+2-14
Original file line numberDiff line numberDiff line change
@@ -493,8 +493,8 @@ without deallocating anything (and so unbounded call-stack depth is avoided).
493493
When the call stack finishes unwinding again, code generated by the END macro
494494
notices this, and calls another routine to deallocate all the objects that
495495
may have been added to the list of deferred deallocations. In effect, a
496-
chain of N deallocations is broken into (N-1)/(PyTrash_UNWIND_LEVEL-1) pieces,
497-
with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL.
496+
chain of N deallocations is broken into (N-1)/(_PyTrash_UNWIND_LEVEL-1) pieces,
497+
with the call stack never exceeding a depth of _PyTrash_UNWIND_LEVEL.
498498
499499
Since the tp_dealloc of a subclass typically calls the tp_dealloc of the base
500500
class, we need to ensure that the trashcan is only triggered on the tp_dealloc
@@ -503,16 +503,6 @@ partially-deallocated object. To check this, the tp_dealloc function must be
503503
passed as second argument to Py_TRASHCAN_BEGIN().
504504
*/
505505

506-
/* This is the old private API, invoked by the macros before 3.2.4.
507-
Kept for binary compatibility of extensions using the stable ABI. */
508-
PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*);
509-
PyAPI_FUNC(void) _PyTrash_destroy_chain(void);
510-
511-
/* This is the old private API, invoked by the macros before 3.9.
512-
Kept for binary compatibility of extensions using the stable ABI. */
513-
PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*);
514-
PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void);
515-
516506
/* Forward declarations for PyThreadState */
517507
struct _ts;
518508

@@ -522,8 +512,6 @@ PyAPI_FUNC(void) _PyTrash_end(struct _ts *tstate);
522512
/* Python 3.10 private API, invoked by the Py_TRASHCAN_BEGIN(). */
523513
PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc);
524514

525-
#define PyTrash_UNWIND_LEVEL 50
526-
527515
#define Py_TRASHCAN_BEGIN_CONDITION(op, cond) \
528516
do { \
529517
PyThreadState *_tstate = NULL; \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Remove 4 private trashcan C API functions which were only kept for the backward
2+
compatibility of the stable ABI with Python 3.8 and older, since the trashcan
3+
API was not usable with the limited C API on Python 3.8 and older. The
4+
trashcan API was excluded from the limited C API in Python 3.9.
5+
6+
Removed functions:
7+
8+
* _PyTrash_deposit_object()
9+
* _PyTrash_destroy_chain()
10+
* _PyTrash_thread_deposit_object()
11+
* _PyTrash_thread_destroy_chain()
12+
13+
The trashcan C API was never usable with the limited C API, since old trashcan
14+
macros accessed directly :c:type:`PyThreadState` members like
15+
``_tstate->trash_delete_nesting``, whereas the :c:type:`PyThreadState`
16+
structure is opaque in the limited C API.
17+
18+
Exclude also the the ``PyTrash_UNWIND_LEVEL`` constant from the C API.
19+
20+
Patch by Victor Stinner.

Misc/stable_abi.txt

-12
Original file line numberDiff line numberDiff line change
@@ -1602,12 +1602,6 @@ function _PyThreadState_Init
16021602
function _PyThreadState_Prealloc
16031603
added 3.2
16041604
abi_only
1605-
function _PyTrash_deposit_object
1606-
added 3.2
1607-
abi_only
1608-
function _PyTrash_destroy_chain
1609-
added 3.2
1610-
abi_only
16111605
data _PyWeakref_CallableProxyType
16121606
added 3.2
16131607
abi_only
@@ -1920,12 +1914,6 @@ function Py_EncodeLocale
19201914
added 3.7 # (and 3.6.1 and 3.5.3)
19211915
function Py_SetPath
19221916
added 3.7 # (and 3.6.1 and 3.5.3)
1923-
function _PyTrash_thread_deposit_object
1924-
added 3.7 # (and 3.6.1 and 3.5.3)
1925-
abi_only
1926-
function _PyTrash_thread_destroy_chain
1927-
added 3.7 # (and 3.6.1 and 3.5.3)
1928-
abi_only
19291917
function PyErr_SetExcFromWindowsErr
19301918
added 3.7 # (and 3.6.1 and 3.5.3)
19311919
ifdef MS_WINDOWS

Objects/object.c

+8-48
Original file line numberDiff line numberDiff line change
@@ -2092,25 +2092,13 @@ Py_ReprLeave(PyObject *obj)
20922092

20932093
/* Trashcan support. */
20942094

2095-
/* Add op to the _PyTrash_delete_later list. Called when the current
2095+
#define _PyTrash_UNWIND_LEVEL 50
2096+
2097+
/* Add op to the gcstate->trash_delete_later list. Called when the current
20962098
* call-stack depth gets large. op must be a currently untracked gc'ed
20972099
* object, with refcount 0. Py_DECREF must already have been called on it.
20982100
*/
2099-
void
2100-
_PyTrash_deposit_object(PyObject *op)
2101-
{
2102-
PyInterpreterState *interp = _PyInterpreterState_GET();
2103-
struct _gc_runtime_state *gcstate = &interp->gc;
2104-
2105-
_PyObject_ASSERT(op, _PyObject_IS_GC(op));
2106-
_PyObject_ASSERT(op, !_PyObject_GC_IS_TRACKED(op));
2107-
_PyObject_ASSERT(op, Py_REFCNT(op) == 0);
2108-
_PyGCHead_SET_PREV(_Py_AS_GC(op), gcstate->trash_delete_later);
2109-
gcstate->trash_delete_later = op;
2110-
}
2111-
2112-
/* The equivalent API, using per-thread state recursion info */
2113-
void
2101+
static void
21142102
_PyTrash_thread_deposit_object(PyObject *op)
21152103
{
21162104
PyThreadState *tstate = _PyThreadState_GET();
@@ -2121,37 +2109,9 @@ _PyTrash_thread_deposit_object(PyObject *op)
21212109
tstate->trash_delete_later = op;
21222110
}
21232111

2124-
/* Deallocate all the objects in the _PyTrash_delete_later list. Called when
2125-
* the call-stack unwinds again.
2126-
*/
2127-
void
2128-
_PyTrash_destroy_chain(void)
2129-
{
2130-
PyInterpreterState *interp = _PyInterpreterState_GET();
2131-
struct _gc_runtime_state *gcstate = &interp->gc;
2132-
2133-
while (gcstate->trash_delete_later) {
2134-
PyObject *op = gcstate->trash_delete_later;
2135-
destructor dealloc = Py_TYPE(op)->tp_dealloc;
2136-
2137-
gcstate->trash_delete_later =
2138-
(PyObject*) _PyGCHead_PREV(_Py_AS_GC(op));
2139-
2140-
/* Call the deallocator directly. This used to try to
2141-
* fool Py_DECREF into calling it indirectly, but
2142-
* Py_DECREF was already called on this object, and in
2143-
* assorted non-release builds calling Py_DECREF again ends
2144-
* up distorting allocation statistics.
2145-
*/
2146-
_PyObject_ASSERT(op, Py_REFCNT(op) == 0);
2147-
++gcstate->trash_delete_nesting;
2148-
(*dealloc)(op);
2149-
--gcstate->trash_delete_nesting;
2150-
}
2151-
}
2152-
2153-
/* The equivalent API, using per-thread state recursion info */
2154-
void
2112+
/* Deallocate all the objects in the gcstate->trash_delete_later list.
2113+
* Called when the call-stack unwinds again. */
2114+
static void
21552115
_PyTrash_thread_destroy_chain(void)
21562116
{
21572117
PyThreadState *tstate = _PyThreadState_GET();
@@ -2192,7 +2152,7 @@ _PyTrash_thread_destroy_chain(void)
21922152
int
21932153
_PyTrash_begin(PyThreadState *tstate, PyObject *op)
21942154
{
2195-
if (tstate->trash_delete_nesting >= PyTrash_UNWIND_LEVEL) {
2155+
if (tstate->trash_delete_nesting >= _PyTrash_UNWIND_LEVEL) {
21962156
/* Store the object (to be deallocated later) and jump past
21972157
* Py_TRASHCAN_END, skipping the body of the deallocator */
21982158
_PyTrash_thread_deposit_object(op);

PC/python3dll.c

-4
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ EXPORT_FUNC(_PyObject_NewVar)
3737
EXPORT_FUNC(_PyState_AddModule)
3838
EXPORT_FUNC(_PyThreadState_Init)
3939
EXPORT_FUNC(_PyThreadState_Prealloc)
40-
EXPORT_FUNC(_PyTrash_deposit_object)
41-
EXPORT_FUNC(_PyTrash_destroy_chain)
42-
EXPORT_FUNC(_PyTrash_thread_deposit_object)
43-
EXPORT_FUNC(_PyTrash_thread_destroy_chain)
4440
EXPORT_FUNC(Py_AddPendingCall)
4541
EXPORT_FUNC(Py_AtExit)
4642
EXPORT_FUNC(Py_BuildValue)

0 commit comments

Comments
 (0)