mirror of
https://github.com/python/cpython.git
synced 2026-05-04 09:31:02 +00:00
Merge 3997f3f5f5 into 3efd2f4db6
This commit is contained in:
commit
415682a2d4
2 changed files with 32 additions and 70 deletions
|
|
@ -8,7 +8,7 @@ extern "C" {
|
|||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_object.h" // Py_DECREF_MORTAL
|
||||
#include "pycore_object.h" // _Py_DECREF_SPECIALIZED
|
||||
#include "pycore_object_deferred.h" // _PyObject_HasDeferredRefcount()
|
||||
|
||||
#include <stdbool.h> // bool
|
||||
|
|
@ -197,11 +197,7 @@ static inline _PyStackRef
|
|||
_PyStackRef_FromPyObjectSteal(PyObject *obj, const char *filename, int linenumber)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
uint16_t flags = 0;
|
||||
if (_Py_IsImmortal(obj)) {
|
||||
flags = Py_TAG_REFCNT;
|
||||
}
|
||||
return _Py_stackref_create(obj, flags, filename, linenumber);
|
||||
return _Py_stackref_create(obj, 0, filename, linenumber);
|
||||
}
|
||||
#define PyStackRef_FromPyObjectSteal(obj) _PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj), __FILE__, __LINE__)
|
||||
|
||||
|
|
@ -294,14 +290,6 @@ _PyStackRef_Borrow(_PyStackRef ref, const char *filename, int linenumber)
|
|||
}
|
||||
#define PyStackRef_Borrow(REF) _PyStackRef_Borrow((REF), __FILE__, __LINE__)
|
||||
|
||||
#define PyStackRef_CLEAR(REF) \
|
||||
do { \
|
||||
_PyStackRef *_tmp_op_ptr = &(REF); \
|
||||
_PyStackRef _tmp_old_op = (*_tmp_op_ptr); \
|
||||
*_tmp_op_ptr = PyStackRef_NULL; \
|
||||
PyStackRef_XCLOSE(_tmp_old_op); \
|
||||
} while (0)
|
||||
|
||||
static inline _PyStackRef
|
||||
_PyStackRef_FromPyObjectStealMortal(PyObject *obj, const char *filename, int linenumber)
|
||||
{
|
||||
|
|
@ -349,8 +337,8 @@ static inline _PyStackRef
|
|||
_PyStackRef_FromPyObjectNewMortal(PyObject *obj, const char *filename, int linenumber)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
assert(!_Py_IsStaticImmortal(obj));
|
||||
Py_INCREF(obj);
|
||||
assert(!_Py_IsImmortal(obj));
|
||||
_Py_INCREF_MORTAL(obj);
|
||||
return _Py_stackref_create(obj, 0, filename, linenumber);
|
||||
}
|
||||
#define PyStackRef_FromPyObjectNewMortal(obj) _PyStackRef_FromPyObjectNewMortal(_PyObject_CAST(obj), __FILE__, __LINE__)
|
||||
|
|
@ -464,45 +452,27 @@ PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref)
|
|||
#define BITS_TO_PTR(REF) ((PyObject *)((REF).bits))
|
||||
#define BITS_TO_PTR_MASKED(REF) ((PyObject *)(((REF).bits) & (~Py_TAG_REFCNT)))
|
||||
|
||||
#define PyStackRef_NULL_BITS Py_TAG_REFCNT
|
||||
static const _PyStackRef PyStackRef_NULL = { .bits = PyStackRef_NULL_BITS };
|
||||
static const _PyStackRef PyStackRef_NULL = { .bits = Py_TAG_REFCNT };
|
||||
|
||||
#define PyStackRef_IsNull(ref) ((ref).bits == PyStackRef_NULL_BITS)
|
||||
#define PyStackRef_True ((_PyStackRef){.bits = ((uintptr_t)&_Py_TrueStruct) | Py_TAG_REFCNT })
|
||||
#define PyStackRef_False ((_PyStackRef){.bits = ((uintptr_t)&_Py_FalseStruct) | Py_TAG_REFCNT })
|
||||
#define PyStackRef_None ((_PyStackRef){.bits = ((uintptr_t)&_Py_NoneStruct) | Py_TAG_REFCNT })
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
// Checks that mask out the deferred bit in the free threading build.
|
||||
#define PyStackRef_IsNone(REF) (((REF).bits & ~Py_TAG_REFCNT) == (uintptr_t)&_Py_NoneStruct)
|
||||
#define PyStackRef_IsNull(REF) (((REF).bits & ~Py_TAG_REFCNT) == (uintptr_t)NULL)
|
||||
#define PyStackRef_IsTrue(REF) (((REF).bits & ~Py_TAG_REFCNT) == (uintptr_t)&_Py_TrueStruct)
|
||||
#define PyStackRef_IsFalse(REF) (((REF).bits & ~Py_TAG_REFCNT) == (uintptr_t)&_Py_FalseStruct)
|
||||
#else
|
||||
#define PyStackRef_IsTrue(REF) ((REF).bits == (((uintptr_t)&_Py_TrueStruct) | Py_TAG_REFCNT))
|
||||
#define PyStackRef_IsFalse(REF) ((REF).bits == (((uintptr_t)&_Py_FalseStruct) | Py_TAG_REFCNT))
|
||||
#define PyStackRef_IsNone(REF) ((REF).bits == (((uintptr_t)&_Py_NoneStruct) | Py_TAG_REFCNT))
|
||||
#endif
|
||||
#define PyStackRef_IsNone(REF) (((REF).bits & ~Py_TAG_REFCNT) == (uintptr_t)&_Py_NoneStruct)
|
||||
|
||||
#define PyStackRef_IsNullOrInt(stackref) (PyStackRef_IsNull(stackref) || PyStackRef_IsTaggedInt(stackref))
|
||||
|
||||
#if defined(Py_DEBUG) && !defined(Py_GIL_DISABLED)
|
||||
#if defined(Py_DEBUG)
|
||||
|
||||
static inline void
|
||||
PyStackRef_CheckValid(_PyStackRef ref)
|
||||
{
|
||||
assert(ref.bits != 0);
|
||||
int tag = ref.bits & Py_TAG_BITS;
|
||||
PyObject *obj = BITS_TO_PTR_MASKED(ref);
|
||||
switch (tag) {
|
||||
case 0:
|
||||
/* Can be immortal if object was made immortal after reference came into existence */
|
||||
assert(!_Py_IsStaticImmortal(obj));
|
||||
break;
|
||||
case Py_TAG_REFCNT:
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
assert((tag == 0) || (tag == Py_TAG_REFCNT));
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -516,7 +486,7 @@ PyStackRef_CheckValid(_PyStackRef ref)
|
|||
#define PyStackRef_AsPyObjectBorrow BITS_TO_PTR_MASKED
|
||||
#define PyStackRef_Borrow(REF) (_PyStackRef){ .bits = ((REF).bits) | Py_TAG_REFCNT};
|
||||
#else
|
||||
/* Does this ref not have an embedded refcount and thus not refer to a declared immmortal object? */
|
||||
/* Does this ref not have an embedded refcount? */
|
||||
static inline int
|
||||
PyStackRef_RefcountOnObject(_PyStackRef ref)
|
||||
{
|
||||
|
|
@ -554,18 +524,9 @@ static inline _PyStackRef
|
|||
PyStackRef_FromPyObjectSteal(PyObject *obj)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
#ifdef Py_GIL_DISABLED
|
||||
return (_PyStackRef){ .bits = (uintptr_t)obj };
|
||||
#else
|
||||
# if SIZEOF_VOID_P > 4
|
||||
unsigned int tag = obj->ob_flags & Py_TAG_REFCNT;
|
||||
# else
|
||||
unsigned int tag = _Py_IsImmortal(obj) ? Py_TAG_REFCNT : 0;
|
||||
# endif
|
||||
_PyStackRef ref = ((_PyStackRef){.bits = ((uintptr_t)(obj)) | tag});
|
||||
_PyStackRef ref = (_PyStackRef){ .bits = (uintptr_t)obj };
|
||||
PyStackRef_CheckValid(ref);
|
||||
return ref;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline _PyStackRef
|
||||
|
|
@ -602,6 +563,7 @@ static inline _PyStackRef
|
|||
_PyStackRef_FromPyObjectNewMortal(PyObject *obj)
|
||||
{
|
||||
assert(obj != NULL);
|
||||
assert(!_Py_IsImmortal(obj));
|
||||
_Py_INCREF_MORTAL(obj);
|
||||
_PyStackRef ref = (_PyStackRef){ .bits = (uintptr_t)obj };
|
||||
PyStackRef_CheckValid(ref);
|
||||
|
|
@ -620,14 +582,14 @@ PyStackRef_FromPyObjectBorrow(PyObject *obj)
|
|||
/* WARNING: This macro evaluates its argument more than once */
|
||||
#ifdef _WIN32
|
||||
#define PyStackRef_DUP(REF) \
|
||||
(PyStackRef_RefcountOnObject(REF) ? (_Py_INCREF_MORTAL(BITS_TO_PTR(REF)), (REF)) : (REF))
|
||||
(PyStackRef_RefcountOnObject(REF) ? (Py_INCREF(BITS_TO_PTR(REF)), (REF)) : (REF))
|
||||
#else
|
||||
static inline _PyStackRef
|
||||
PyStackRef_DUP(_PyStackRef ref)
|
||||
{
|
||||
assert(!PyStackRef_IsNull(ref));
|
||||
if (PyStackRef_RefcountOnObject(ref)) {
|
||||
_Py_INCREF_MORTAL(BITS_TO_PTR(ref));
|
||||
Py_INCREF(BITS_TO_PTR(ref));
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
|
@ -636,14 +598,15 @@ PyStackRef_DUP(_PyStackRef ref)
|
|||
static inline bool
|
||||
PyStackRef_IsHeapSafe(_PyStackRef ref)
|
||||
{
|
||||
#ifdef Py_GIL_DISABLED
|
||||
if ((ref.bits & Py_TAG_BITS) != Py_TAG_REFCNT) {
|
||||
if ((ref.bits & Py_TAG_BITS) != Py_TAG_REFCNT || PyStackRef_IsNull(ref)) {
|
||||
// Tagged ints and ERROR are included.
|
||||
return true;
|
||||
}
|
||||
PyObject *obj = BITS_TO_PTR_MASKED(ref);
|
||||
return obj == NULL || _PyObject_HasDeferredRefcount(obj);
|
||||
#ifdef Py_GIL_DISABLED
|
||||
return _PyObject_HasDeferredRefcount(obj);
|
||||
#else
|
||||
return (ref.bits & Py_TAG_BITS) != Py_TAG_REFCNT || ref.bits == PyStackRef_NULL_BITS || _Py_IsImmortal(BITS_TO_PTR_MASKED(ref));
|
||||
return _Py_IsImmortal(obj);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -671,7 +634,7 @@ PyStackRef_AsStrongReference(_PyStackRef stackref)
|
|||
#define PyStackRef_CLOSE(REF) \
|
||||
do { \
|
||||
_PyStackRef _temp = (REF); \
|
||||
if (PyStackRef_RefcountOnObject(_temp)) Py_DECREF_MORTAL(BITS_TO_PTR(_temp)); \
|
||||
if (PyStackRef_RefcountOnObject(_temp)) Py_DECREF(BITS_TO_PTR(_temp)); \
|
||||
} while (0)
|
||||
#else
|
||||
static inline void
|
||||
|
|
@ -679,7 +642,7 @@ PyStackRef_CLOSE(_PyStackRef ref)
|
|||
{
|
||||
assert(!PyStackRef_IsNull(ref));
|
||||
if (PyStackRef_RefcountOnObject(ref)) {
|
||||
Py_DECREF_MORTAL(BITS_TO_PTR(ref));
|
||||
Py_DECREF(BITS_TO_PTR(ref));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -689,7 +652,7 @@ PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct)
|
|||
{
|
||||
assert(!PyStackRef_IsNull(ref));
|
||||
if (PyStackRef_RefcountOnObject(ref)) {
|
||||
Py_DECREF_MORTAL_SPECIALIZED(BITS_TO_PTR(ref), destruct);
|
||||
_Py_DECREF_SPECIALIZED(BITS_TO_PTR(ref), destruct);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -702,11 +665,18 @@ PyStackRef_XCLOSE(_PyStackRef ref)
|
|||
assert(ref.bits != 0);
|
||||
if (PyStackRef_RefcountOnObject(ref)) {
|
||||
assert(!PyStackRef_IsNull(ref));
|
||||
Py_DECREF_MORTAL(BITS_TO_PTR(ref));
|
||||
Py_DECREF(BITS_TO_PTR(ref));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Note: this is a macro because MSVC (Windows) has trouble inlining it.
|
||||
|
||||
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits & (~Py_TAG_REFCNT)))
|
||||
|
||||
|
||||
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||
|
||||
#define PyStackRef_CLEAR(REF) \
|
||||
do { \
|
||||
_PyStackRef *_tmp_op_ptr = &(REF); \
|
||||
|
|
@ -715,14 +685,6 @@ PyStackRef_XCLOSE(_PyStackRef ref)
|
|||
PyStackRef_XCLOSE(_tmp_old_op); \
|
||||
} while (0)
|
||||
|
||||
|
||||
// Note: this is a macro because MSVC (Windows) has trouble inlining it.
|
||||
|
||||
#define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits & (~Py_TAG_REFCNT)))
|
||||
|
||||
|
||||
#endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||
|
||||
static inline PyTypeObject *
|
||||
PyStackRef_TYPE(_PyStackRef stackref) {
|
||||
if (PyStackRef_IsTaggedInt(stackref)) {
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ ## Converting to and from PyObject*
|
|||
Three conversions control ownership:
|
||||
|
||||
- `PyStackRef_FromPyObjectNew(obj)` - create a new reference (INCREF if mortal).
|
||||
- `PyStackRef_FromPyObjectSteal(obj)` - take over ownership without changing the count unless the
|
||||
object is immortal.
|
||||
- `PyStackRef_FromPyObjectSteal(obj)` - take over ownership without changing the count;
|
||||
this function is very lightweight since it does not check or modify any refcount.
|
||||
- `PyStackRef_FromPyObjectBorrow(obj)` - create a borrowed stackref (never decref on close).
|
||||
|
||||
The `obj` argument must not be `NULL`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue