mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-133164: Add PyUnstable_Object_IsUniqueReferencedTemporary
C API (gh-133170)
After gh-130704, the interpreter replaces some uses of `LOAD_FAST` with `LOAD_FAST_BORROW` which avoid incref/decrefs by "borrowing" references on the interpreter stack when the bytecode compiler can determine that it's safe. This change broke some checks in C API extensions that relied on `Py_REFCNT()` of `1` to determine if it's safe to modify an object in-place. Objects may have a reference count of one, but still be referenced further up the interpreter stack due to borrowing of references. This provides a replacement function for those checks. `PyUnstable_Object_IsUniqueReferencedTemporary` is more conservative: it checks that the object has a reference count of one and that it exists as a unique strong reference in the interpreter's stack of temporary variables in the top most frame. See also: * https://github.com/numpy/numpy/issues/28681 Co-authored-by: Pieter Eendebak <pieter.eendebak@gmail.com> Co-authored-by: T. Wouters <thomas@python.org> Co-authored-by: mpage <mpage@cs.stanford.edu> Co-authored-by: Mark Shannon <mark@hotpy.org> Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
4701ff92d7
commit
f2379535fe
8 changed files with 109 additions and 0 deletions
|
@ -15,6 +15,7 @@
|
|||
#include "pycore_hamt.h" // _PyHamtItems_Type
|
||||
#include "pycore_initconfig.h" // _PyStatus_OK()
|
||||
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_Type
|
||||
#include "pycore_interpframe.h" // _PyFrame_Stackbase()
|
||||
#include "pycore_interpolation.h" // _PyInterpolation_Type
|
||||
#include "pycore_list.h" // _PyList_DebugMallocStats()
|
||||
#include "pycore_long.h" // _PyLong_GetZero()
|
||||
|
@ -2621,6 +2622,29 @@ PyUnstable_Object_EnableDeferredRefcount(PyObject *op)
|
|||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
PyUnstable_Object_IsUniqueReferencedTemporary(PyObject *op)
|
||||
{
|
||||
if (!_PyObject_IsUniquelyReferenced(op)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_PyInterpreterFrame *frame = _PyEval_GetFrame();
|
||||
if (frame == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_PyStackRef *base = _PyFrame_Stackbase(frame);
|
||||
_PyStackRef *stackpointer = frame->stackpointer;
|
||||
while (stackpointer > base) {
|
||||
stackpointer--;
|
||||
if (op == PyStackRef_AsPyObjectBorrow(*stackpointer)) {
|
||||
return PyStackRef_IsHeapSafe(*stackpointer);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyUnstable_TryIncRef(PyObject *op)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue