-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
gh-133164: Add PyUnstable_Object_IsUniqueReferencedTemporary
C API
#133170
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
Changes from 2 commits
32b6cd0
479f185
4a53a98
fdc438a
b6508df
07ba540
99e3265
0e0e674
07f3b23
bba589f
f23de33
6efe2fb
f30ccf4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -613,6 +613,30 @@ Object Protocol | |
|
||
.. versionadded:: 3.14 | ||
|
||
.. c:function:: int PyUnstable_Object_IsUniqueTemporary(PyObject *obj) | ||
|
||
Check if *obj* is a unique temporary object on the top most frame of the | ||
interpreter stack. Returns ``1`` if *obj* is a unique temporary object, | ||
colesbury marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
and ``0`` otherwise. This check is conservative, and may return ``0`` | ||
in some cases even if *obj* is a unique temporary object. | ||
|
||
If an object is a unique temporary, it is guaranteed that the reference | ||
count is ``1`` and it may be safe to modify the object in-place becuase | ||
colesbury marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
it is not visible to any other code. | ||
ZeroIntensity marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
In the example below, ``my_func`` is called with a unique temporary object | ||
as its argument:: | ||
|
||
my_func([1, 2, 3]) | ||
|
||
In the example below, ``my_func`` is **not** called with a unique temporary | ||
object as its argument:: | ||
colesbury marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
my_list = [1, 2, 3] | ||
my_func(my_list) | ||
|
||
vstinner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.. versionadded:: 3.14 | ||
|
||
.. c:function:: int PyUnstable_IsImmortal(PyObject *obj) | ||
|
||
This function returns non-zero if *obj* is :term:`immortal`, and zero | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Added the :c:func:`PyUnstable_Object_IsUniqueTemporary` function for | ||
ZeroIntensity marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
determining if an object exists as a unqiue temporary variable on the | ||
interpreter's stack. This is a replacement for some cases where checking | ||
that :c:func:`Py_REFCNT` is one is no longer sufficient to determine if it's | ||
safe to modify a Python object in-place with no visible side effects. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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_list.h" // _PyList_DebugMallocStats() | ||
#include "pycore_long.h" // _PyLong_GetZero() | ||
#include "pycore_memoryobject.h" // _PyManagedBuffer_Type | ||
|
@@ -2616,6 +2617,35 @@ PyUnstable_Object_EnableDeferredRefcount(PyObject *op) | |
#endif | ||
} | ||
|
||
int | ||
PyUnstable_Object_IsUniqueTemporary(PyObject *op) | ||
{ | ||
if (!_PyObject_IsUniquelyReferenced(op)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this just demonstrates that We need to check that the following are true:
I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's discuss the name for |
||
return 0; | ||
} | ||
|
||
_PyInterpreterFrame *frame = _PyEval_GetFrame(); | ||
if (frame == NULL) { | ||
return 0; | ||
} | ||
|
||
_PyStackRef *base = _PyFrame_Stackbase(frame); | ||
_PyStackRef *stackpointer = frame->stackpointer; | ||
int found = 0; | ||
colesbury marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
while (stackpointer > base) { | ||
stackpointer--; | ||
if (op == PyStackRef_AsPyObjectBorrow(*stackpointer)) { | ||
if (!PyStackRef_IsHeapSafe(*stackpointer)) { | ||
return 0; | ||
} | ||
found++; | ||
ZeroIntensity marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
colesbury marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
// Check that we found exactly one reference to `op` | ||
return found == 1; | ||
colesbury marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
int | ||
PyUnstable_TryIncRef(PyObject *op) | ||
{ | ||
|
Uh oh!
There was an error while loading. Please reload this page.